我有下表(对于oracle和sql server,我需要它们):
id id_reference
1 0
2 1
3 1
4 1
6 2
7 2
8 3
9 8
10 0
11 10
12 10
13 12
我想获取每个id的id_reference的计数。
结果
id count(1)
1 7 -- because id 1 2 3 4 and the child 6 7 8 9 are referring to the id
2 2 -- because id 6 and 7 are referring to it
3 2 -- because id 8 and the child 9 referring to it
4 0 -- non are referring to them
6 0 -- non are referring to them
7 0 -- non are referring to them
8 1 -- because 9 is referring to the id
10 3 -- because 11 , 12 and 13 are referring
11 0 -- none are referring
12 1 -- 13 is referring to id
13 0 -- none is referring to id
这是我尝试过的,但是我需要递归。
select count(1),
id,
(select count(1) from tab e2 where e2.id <=e1.id and id_ref in ( select id from tab e3 where e3.id_ref= e2.id )
from tab e1
group by id
order by id desc
答案 0 :(得分:2)
Oracle版本:
select distinct id, nvl(cnt, 0)
from tab
left join (
select root, count(1) cnt
from (
select tab.*, connect_by_root(id) root
from tab
where level > 1
connect by id_reference = prior id)
group by root) r on root = tab.id
order by id
答案 1 :(得分:1)
在SQL Server(2016+)中,这是实现上述结果集的方式:
USE Sandbox;
GO
WITH VTE AS(
SELECT *
FROM (VALUES (1 ,0 ),
(2 ,1 ),
(3 ,1 ),
(4 ,1 ),
(6 ,2 ),
(7 ,2 ),
(8 ,3 ),
(9 ,8 ),
(10,0 ),
(11,10),
(12,10),
(13,12)) V(ID, ID_ref)),
CTE AS (
SELECT ID,
CONVERT(varchar(30),CONVERT(varchar(4),ID)) AS Delimited
FROM VTE V
WHERE V.ID_ref = 0
UNION ALL
SELECT V.ID,
CONVERT(varchar(30),CONCAT(C.Delimited,',' + CONVERT(varchar(4),V.ID)))
FROM CTE C
JOIN VTE V ON V.ID_ref = C.ID),
Splits AS(
SELECT C.ID,
SS.value
FROM CTE C
CROSS APPLY STRING_SPLIT(C.Delimited,',') SS)
SELECT V.ID,
COUNT(S.ID) - 1 AS [Count]
FROM VTE V
JOIN Splits S ON S.[value] = V.ID
GROUP BY V.ID;
这首先在每个层创建每个ID的分隔列表。然后将它们分开,最后进行Count -1。
如果您未使用SQL Server 2016+,则可以使用XML拆分器或delimitedsplit8k(_lead)
。
请注意,rCTe将在100个循环后停止递归。您将需要使用OPTION (MAXRECURSION N)
来增加循环次数(其中N
是您可能拥有的最大图层的合适数目)。