我有这种结构的观点:
EntryId | EntryName | ParentEntryId | Depth | DatePosted
我想要做的是编写一个SQL查询,它将带有Depth = 0的前两个条目以及第一个后代(基于ParentEntryId)。下面,我提供了一个示例输出。
EntryId | EntryName | ParentEntryId | Depth | DatePosted | ChildCount
1 | a | NULL | 0 | 1/12/2012 | 2
4 | b | 1 | 1 | 1/14/2012 | 5
13 | c | 1 | 1 | 1/15/2012 | 3
3 | d | NULL | 0 | 1/11/2012 | 1
12 | e | 3 | 1 | 1/14/2012 | 0
我知道我可以像这样轻松地输入深度= 0的条目:
SELECT TOP 10 FROM Entries WHERE Depth=0 ORDER BY DatePosted DESC
但是,我不知道如何带来相关的子条目。例如,对于Id = 1的主条目,我想带上ParentEntryId = 1的条目(第一个后代)。我还需要带来这些第一个后代的子条目的计数。有什么想法吗?
答案 0 :(得分:2)
根据您更新的问题,以下查询将产生完美的结果
SELECT
EntryId , EntryName , ParentEntryId , Depth , DatePosted, ChildCount
FROM
(
SELECT
TOP 10
E1.EntryId , E1.EntryName , E1.ParentEntryId , E1.Depth , E1.DatePosted,
(
SELECT
COUNT(1)
FROM Entries E2
WHERE E2.ParentEntryID =E1.EntryID
) as ChildCount
FROM Entries E1
WHERE E1.Depth=0
UNION
SELECT
E1.EntryId , E1.EntryName , E1.ParentEntryId , E1.Depth , E1.DatePosted,
(
SELECT
COUNT(1)
FROM Entries E3
WHERE E3.ParentEntryID =E1.EntryID
) as ChildCount
FROM Entries E1
LEFT JOIN Entries E2 ON E1.ParentEntryID= E2.EntryID AND E2.Depth=0
)
ORDER BY ParentEntryID , Depth ASC, DatePosted
答案 1 :(得分:1)
您也可以使用递归cte进行此操作..如果您在大型记录集上使用此功能,则应确保性能符合您的标准
;WITH cte AS (
SELECT [EntryId],
[EntryName],
[ParentEntryId],
[Depth],
[DatePosted],
[EntryId] [Root],
ROW_NUMBER() OVER (ORDER BY DatePosted DESC) [Rn],
CAST(EntryId AS VARCHAR(MAX)) [Path]
FROM Entries
WHERE [Depth] = 0
UNION ALL
SELECT e.[EntryId],
e.[EntryName],
e.[ParentEntryId],
e.[Depth],
e.[DatePosted],
[Root],
Rn,
[Path] + ',' + CAST(e.EntryId AS VARCHAR(MAX))
FROM Entries e
JOIN cte ON cte.EntryID = e.ParentEntryId
)
SELECT [EntryId],
[EntryName],
[ParentEntryId],
[Depth],
[DatePosted],
ChildCount
FROM cte c1
OUTER APPLY (SELECT COUNT (*) - 1 AS ChildCount
FROM cte c2
WHERE c2.[Path] LIKE c1.[Path] + '%'
) oa
WHERE Rn <= 2 -- only gets the first 2 records with depth = 0
AND Depth <= 1 -- limit to only top level child records
ORDER BY [Root],
[ParentEntryID]
答案 2 :(得分:1)
如果没有任何输入数据,很难给出准确的答案。但是,我认为这就是你要找的东西。
我使用了一个简单的数据集进行测试。我试图对脚本的布局进行分组,以便您可以根据ParentEntryID轻松查看子项数:
-- Create a table.
DROP TABLE Entries
CREATE TABLE Entries
(
EntryID INT,
EntryName VARCHAR(20),
ParentEntryID INT,
Depth INT,
DatePosted DATE
);
-- Populate the table
INSERT INTO Entries VALUES
(1, 'A', null, null, CURRENT_TIMESTAMP)
,(73, 'C', 1, 0, CURRENT_TIMESTAMP)
,(16, 'B', 73, 1, CURRENT_TIMESTAMP)
,(85, 'G', 73, 1, DATEADD(DAY, 1, CURRENT_TIMESTAMP))
,(74, 'D', 73, 1, CURRENT_TIMESTAMP)
,(75, 'E', 74, 2, CURRENT_TIMESTAMP)
,(76, 'F', 74, 2, CURRENT_TIMESTAMP)
,(86, 'H', 85, 3, DATEADD(DAY, 2, CURRENT_TIMESTAMP))
,(87, 'I', 85, 3, DATEADD(DAY, 2, CURRENT_TIMESTAMP))
,(88, 'J', 86, 4, DATEADD(DAY, 3, CURRENT_TIMESTAMP))
,(89, 'K', 88, 5, CURRENT_TIMESTAMP)
,(90, 'L', 88, 5, CURRENT_TIMESTAMP)
,(91, 'M', 88, 5, CURRENT_TIMESTAMP)
,(92, 'N', 88, 5, CURRENT_TIMESTAMP);
然后您可以使用递归公用表表达式。我已评论TOP 2
和WHERE Depth = 0
以提供更多结果。 (我认为这使得基于少量测试数据更容易理解。)您可以将这些替换为您的要求。
;WITH MyEntries (EntryID, ParentEntryID, EntryName, Depth, DatePosted)
AS
(
-- Anchor
SELECT EntryID, ParentEntryID, EntryName, Depth, DatePosted
FROM Entries
--WHERE Depth = 0
UNION ALL
-- Recursive
SELECT Recurs.EntryID, Recurs.ParentEntryID, Recurs.EntryName, Recurs.Depth, Recurs.DatePosted
FROM Entries AS Recurs
INNER JOIN MyEntries AS Anchor
ON Recurs.EntryID = Anchor.ParentEntryID
--WHERE Recurs.Depth = 0
)
SELECT DISTINCT
--TOP 2
ME.EntryID
,ME.ParentEntryID
,ME.EntryName
,ME.Depth
,ME.DatePosted
,COALESCE(VT.ChildCOunt, 0) AS 'ChildCount'
FROM MyEntries AS ME
LEFT JOIN (SELECT ParentEntryID, COUNT(1) AS 'ChildCount'
FROM Entries
GROUP BY ParentEntryID ) AS VT
ON ME.EntryID = VT.ParentEntryID
ORDER BY
ME.DatePosted;
我不确定这是最有效的方式,但似乎有效。
答案 3 :(得分:0)
你有前十名但没有订单,所以你的逻辑从一开始就有缺陷。您也没有列出任何列。作为一个纯粹的猜测,因为你没有提供太多的细节,我在想这样的事情。
select [Columns]
from Entries
where ParentEntryID in
(
select top 10 EntryID
from Entries
where Depth = 10
order by SomeColumn
)
或许你需要一个递归的cte来获得每棵树下的整棵树?