我有一个简单的表,其中包含叶子和子叶信息。 (比如论坛问题)
定义主消息,其中childId
和ParentID
相同
所以我们在这里看到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
(我不想使用光标)
答案 0 :(得分: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;
答案 1 :(得分:8)
要向客户端呈现多个结果集,您将不得不使用游标或while循环来执行独立的SELECT
操作。您无法从CTE执行此操作,因为CTE只能由一个后续查询使用。
现在,问题的根源与游标无关,但事实上你正在使用HTML转发器。为什么需要为此使用HTML转发器?一个简单的DataReader可以循环遍历CTE的单集的所有结果,并根据循环做出条件格式化决策,并确定根ID的变化。因此,我建议您尝试以不同的方式解决表示问题,而不是试图强制SQL Server来适应您的表示实现。
答案 2 :(得分: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;
答案 3 :(得分:-2)
您可以在root问题的锚点部分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
)