4

我有一个简单的表,其中包含叶子和子叶子信息。(就像一个论坛问题)

消息定义在哪里和childIdParentID相同的

在此处输入图像描述

所以在这里我们看到 2 个主要问题及其答案。

我还设法计算了每个元素的深度:

在此处输入图像描述

简而言之,这是主要查询:

    WITH CTE AS
    (
       SELECT childID
             ,parentID,
             0 AS depth,name
       FROM   @myTable
       WHERE   childID = parentID AND childID=1 -- problem line
       
       UNION ALL
       
       SELECT TBL.childID
             ,TBL.parentID,
              CTE.depth + 1 , TBL.name 
       FROM   @myTable AS TBL
               INNER JOIN CTE  ON  TBL.parentID = CTE.childID
       WHERE   TBL.childID<>TBL.parentID
    )
    SELECT childID,parentID,REPLICATE('----', depth) + name        

但问题是第 8 行(已评论)。

我目前问“给我所有问题 id #1 的集群”

那么问题出在哪里?

我想为每个问题设置多个结果集!

所以在这里我需要有2个结果集:

childId=parentId=1 换一换childId=parentId=6

在线完整的工作sql

(我不想使用光标)

4

4 回答 4

9

您可以动态构建查询。

DECLARE @SQL NVARCHAR(MAX) =
(SELECT '
WITH CTE AS
(
   SELECT childID
         ,parentID,
         0 AS depth,name
   FROM   myTable
   WHERE   childID = parentID AND childID = '+CAST(childID AS NVARCHAR(10))+'

   UNION ALL

   SELECT TBL.childID
         ,TBL.parentID,
          CTE.depth + 1 , TBL.name 
   FROM   myTable AS TBL
           INNER JOIN CTE  ON  TBL.parentID = CTE.childID
   WHERE   TBL.childID<>TBL.parentID
)
SELECT childID,parentID,REPLICATE(''----'', depth) + name
FROM   CTE   
ORDER BY
      childID;'

FROM  myTable
WHERE childID = parentID
FOR XML PATH(''), TYPE).value('text()[1]', 'NVARCHAR(MAX)');

EXEC sp_executesql @SQL;

更新:

正如 Bogdan Sahlean 所建议的,我们可以通过使实际查询参数化来最小化编译。

DECLARE @SQL1 NVARCHAR(MAX) =
'WITH CTE AS
(
   SELECT childID
         ,parentID,
         0 AS depth,name
   FROM   myTable
   WHERE   childID = parentID AND childID = @childID

   UNION ALL

   SELECT TBL.childID
         ,TBL.parentID,
          CTE.depth + 1 , TBL.name 
   FROM   myTable AS TBL
           INNER JOIN CTE  ON  TBL.parentID = CTE.childID
   WHERE   TBL.childID<>TBL.parentID
)
SELECT childID,parentID,REPLICATE(''----'', depth) + name
FROM   CTE   
ORDER BY
      childID;'

DECLARE @SQL2 NVARCHAR(MAX) =
(SELECT 'exec sp_executesql @SQL, N''@childID int'', '+CAST(childID AS NVARCHAR(10))+';'
FROM  myTable
WHERE childID = parentID
FOR XML PATH(''), TYPE).value('text()[1]', 'NVARCHAR(MAX)');

EXEC sp_executesql @SQL2, N'@SQL NVARCHAR(MAX)', @SQL1;
于 2013-08-03T17:46:28.203 回答
8

要将多个结果集呈现给您的客户端,您将不得不使用游标或 while 循环来执行独立SELECT操作。您不能从 CTE 执行此操作,因为 CTE 只能被一个后续查询使用。

现在,问题的根源实际上与游标无关,而是您使用的是 HTML 中继器这一事实。为什么需要为此使用 HTML 转发器?一个简单的 DataReader 可以遍历 CTE 的单个集合中的所有结果,并根据循环和确定根 ID 何时更改来做出有条件的格式化决策。因此,我建议您考虑以不同的方式解决演示问题,而不是试图强制 SQL Server 适应您的演示实现。

于 2013-08-03T17:46:14.183 回答
0

我不确定“返回两个结果集”是什么意思。您可以只拥有一个结果集,并将根问题分配到另一列吗?对您的查询进行以下调整:

WITH CTE AS (
      SELECT ChildId as WhichQuestion, childID, parentID, 0 AS depth, name
      FROM   @myTable
      WHERE   childID = parentID
      UNION ALL
      SELECT cte.WhichQuestion, TBL.childID, TBL.parentID, CTE.depth + 1 , TBL.name 
      FROM   @myTable AS TBL
            INNER JOIN CTE  ON  TBL.parentID = CTE.childID
      WHERE   TBL.childID <> TBL.parentID
    )
SELECT WhichQuestion, childID, parentID, REPLICATE('----', depth) + name     
FROM   CTE   
ORDER BY WhichQuestion, childID;
于 2013-08-03T18:16:18.097 回答
-2

您可以保存在根问题的锚部分 childId 中,然后通过所需的 Id 访问所有分支:

WITH CTE AS (
    SELECT childID as RootId
        , childID
        , parentID
        , 0 AS depth,name
    FROM @myTable
    WHERE childID = parentID
    UNION ALL
    SELECT CTE.RootId
        , TBL.childID
        , TBL.parentID
        , CTE.depth + 1 , TBL.name 
    FROM @myTable AS TBL
    INNER JOIN CTE  ON  TBL.parentID = CTE.childID
    WHERE TBL.childID<>TBL.parentID
)
于 2013-08-03T17:18:39.113 回答