получить счетчик ссылочного идентификатора, и это их ребенок рекурсивно - PullRequest
0 голосов
/ 07 февраля 2019

У меня есть таблица ниже (они нужны мне для сервера Oracle и SQL):

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_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

Ответы [ 2 ]

0 голосов
/ 07 февраля 2019

В 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;

Сначала создается список с разделителями для каждого идентификатора на каждом уровне.Затем он разделяет их и, наконец, выполняет подсчет -1.

. Если вы не используете SQL Server 2016+, вы можете использовать разделитель XML или delimitedsplit8k(_lead).

* 1009.* Обратите внимание, что rCTe перестанет повторяться при 100 циклах.Вам нужно будет использовать OPTION (MAXRECURSION N), чтобы увеличить количество циклов (где N - подходящее число максимального слоя, который у вас может быть).

0 голосов
/ 07 февраля 2019

Версия Oracle:

Демоверсия dbfiddle

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...