递归 SQL 查询(父子)以包含每条记录的总下线记录
Recursive SQL query (parent-child) to include total downline records per record
我有一个 table 具有父子结构。
我设法通过创建一个名为“Path”的字段并使用代理的名字对这个结构进行排序,所以这个查询:
WITH cte(PLID, sponsorid, firstname, lastname, Status, LEVEL, path) AS (SELECT
PLID, sponsorid, firstname, lastname, Status, 0 AS LEVEL, CAST(firstname AS VARCHAR(1000)) AS path
FROM TEST WHERE PLID =1 UNION ALL
SELECT c.PLID, c.sponsorid, c.firstname, c.lastname, c.Status, cte. LEVEL + 1 AS LEVEL,
CAST((cte.path + '/' + c.firstname) AS VARCHAR(1000))
AS path FROM TEST c INNER JOIN cte ON c.sponsorid = cte.plid)
SELECT PLID, sponsorid, firstname, lastname, Status, LEVEL, path
FROM cte ORDER BY path ASC
...returns 这个,树视图数据:
+------+-----------+-----------+----------+--------+-------+-------------------------------------+
| PLID | SPONSORID | FIRSTNAME | LASTNAME | STATUS | LEVEL | PATH |
+------+-----------+-----------+----------+--------+-------+-------------------------------------+
| 1 | 0 | Danielle | Lipsin | 1 | 0 | Danielle |
| 4 | 1 | Alissa | Doe | 1 | 1 | Danielle/Alissa |
| 2 | 1 | Charles | Doe | 1 | 1 | Danielle/Charles |
| 6 | 2 | Mark | Doe | 1 | 2 | Danielle/Charles/Mark |
| 5 | 2 | Martin | Doe | 1 | 2 | Danielle/Charles/Martin |
| 8 | 5 | Katy | Perry | 1 | 3 | Danielle/Charles/Martin/Katy |
| 7 | 5 | Leo | Messi | 1 | 3 | Danielle/Charles/Martin/Leo |
| 9 | 7 | Alex | Doe | 1 | 4 | Danielle/Charles/Martin/Leo/Alex |
| 10 | 7 | Laureen | Doe | 1 | 4 | Danielle/Charles/Martin/Leo/Laureen |
| 3 | 1 | Michelle | Doe | 1 | 1 | Danielle/Michelle |
+------+-----------+-----------+----------+--------+-------+-------------------------------------+
我试图做一个嵌套的 select 但它没有用。在每条记录中包含儿童总数的最佳方法是什么?
预期结果:
+------+-----------+-----------+----------+--------+-------+-------------------------------------+---------------+
| PLID | SPONSORID | FIRSTNAME | LASTNAME | STATUS | LEVEL | PATH | TotalDownline |
+------+-----------+-----------+----------+--------+-------+-------------------------------------+---------------+
| 1 | 0 | Danielle | Lipsin | 1 | 0 | Danielle | 9 |
| 4 | 1 | Alissa | Doe | 1 | 1 | Danielle/Alissa | 0 |
| 2 | 1 | Charles | Doe | 1 | 1 | Danielle/Charles | 7 |
| 6 | 2 | Mark | Doe | 1 | 2 | Danielle/Charles/Mark | 0 |
| 5 | 2 | Martin | Doe | 1 | 2 | Danielle/Charles/Martin | 4 |
| 8 | 5 | Katy | Perry | 1 | 3 | Danielle/Charles/Martin/Katy | 0 |
| 7 | 5 | Leo | Messi | 1 | 3 | Danielle/Charles/Martin/Leo | 2 |
| 9 | 7 | Alex | Doe | 1 | 4 | Danielle/Charles/Martin/Leo/Alex | 0 |
| 10 | 7 | Laureen | Doe | 1 | 4 | Danielle/Charles/Martin/Leo/Laureen | 0 |
| 3 | 1 | Michelle | Doe | 1 | 1 | Danielle/Michelle | 0 |
+------+-----------+-----------+----------+--------+-------+-------------------------------------+---------------+
谢谢。
CREATE TABLE TEST (
PLID int,
sponsorid int,
firstname nvarchar(50),
lastname nvarchar(50),
status int
);
INSERT INTO TEST VALUES (1,0,'Danielle', 'Lipsin', 1);
INSERT INTO TEST VALUES (2,1,'Charles', 'Doe', 1);
INSERT INTO TEST VALUES (3,1,'Michelle', 'Doe', 1);
INSERT INTO TEST VALUES (4,1,'Alissa', 'Doe', 1);
INSERT INTO TEST VALUES (5,2,'Martin', 'Doe', 1);
INSERT INTO TEST VALUES (6,2,'Mark', 'Doe', 1);
INSERT INTO TEST VALUES (7,5,'Leo', 'Messi', 1);
INSERT INTO TEST VALUES (8,5,'Katy', 'Perry', 1);
INSERT INTO TEST VALUES (9,7,'Alex', 'Doe', 1);
INSERT INTO TEST VALUES (10,7,'Laureen', 'Doe', 1);
好的,您可以采用一种可能的方式,但不确定这是最好的方式。
- 根据与现有
path
(名称)相同的原则创建一个新列 pathid
,但每个人都是唯一的。
- 通过对 CTE 使用子查询,计算
id
在 pathid
中出现的次数,而不是我们的。
WITH cte1 (PLID, sponsorid, firstname, lastname, [Status], [LEVEL], [path], pathid) AS (
SELECT PLID, sponsorid, firstname, lastname, [Status], 0 AS [LEVEL]
, CAST(firstname AS VARCHAR(1000)) AS [path]
, CAST('/' + CAST(PLID AS varchar(38)) AS varchar(max)) AS pathid
FROM #TEST
WHERE PLID = 1--94
UNION ALL
SELECT c.PLID, c.sponsorid, c.firstname, c.lastname, c.[Status], cte1.[LEVEL] + 1 AS [LEVEL]
, CAST((cte1.[path] + '/' + c.firstname) AS VARCHAR(1000)) AS [path]
, CAST(cte1.pathid + '/' + cast(c.PLID AS varchar(38)) AS varchar(max)) AS pathid
FROM #TEST c
INNER JOIN cte1 ON c.sponsorid = cte1.plid
)
SELECT PLID, sponsorid, firstname, lastname, [Status], [LEVEL], [path], pathid
, (select count(*) from cte1 B where B.pathid + '/' like '%/' + cast(A.PLID AS varchar(38)) + '/%' and B.PLID <> A.PLID)
FROM cte1 A
ORDER BY [path] ASC;
Returns 您的示例数据:
PLID
sponsorid
firstname
lastname
Status
LEVEL
path
pathid
Total Downline
1
0
Danielle
Lipsin
1
0
Danielle
/1
9
4
1
Alissa
Doe
1
1
Danielle/Alissa
/1/4
0
2
1
Charles
Doe
1
1
Danielle/Charles
/1/2
6
6
2
Mark
Doe
1
2
Danielle/Charles/Mark
/1/2/6
0
5
2
Martin
Doe
1
2
Danielle/Charles/Martin
/1/2/5
4
8
5
Katy
Perry
1
3
Danielle/Charles/Martin/Katy
/1/2/5/8
0
7
5
Leo
Messi
1
3
Danielle/Charles/Martin/Leo
/1/2/5/7
2
9
7
Alex
Doe
1
4
Danielle/Charles/Martin/Leo/Alex
/1/2/5/7/9
0
10
7
Laureen
Doe
1
4
Danielle/Charles/Martin/Leo/Laureen
/1/2/5/7/10
0
3
1
Michelle
Doe
1
1
Danielle/Michelle
/1/3
0
我有一个 table 具有父子结构。
我设法通过创建一个名为“Path”的字段并使用代理的名字对这个结构进行排序,所以这个查询:
WITH cte(PLID, sponsorid, firstname, lastname, Status, LEVEL, path) AS (SELECT
PLID, sponsorid, firstname, lastname, Status, 0 AS LEVEL, CAST(firstname AS VARCHAR(1000)) AS path
FROM TEST WHERE PLID =1 UNION ALL
SELECT c.PLID, c.sponsorid, c.firstname, c.lastname, c.Status, cte. LEVEL + 1 AS LEVEL,
CAST((cte.path + '/' + c.firstname) AS VARCHAR(1000))
AS path FROM TEST c INNER JOIN cte ON c.sponsorid = cte.plid)
SELECT PLID, sponsorid, firstname, lastname, Status, LEVEL, path
FROM cte ORDER BY path ASC
...returns 这个,树视图数据:
+------+-----------+-----------+----------+--------+-------+-------------------------------------+
| PLID | SPONSORID | FIRSTNAME | LASTNAME | STATUS | LEVEL | PATH |
+------+-----------+-----------+----------+--------+-------+-------------------------------------+
| 1 | 0 | Danielle | Lipsin | 1 | 0 | Danielle |
| 4 | 1 | Alissa | Doe | 1 | 1 | Danielle/Alissa |
| 2 | 1 | Charles | Doe | 1 | 1 | Danielle/Charles |
| 6 | 2 | Mark | Doe | 1 | 2 | Danielle/Charles/Mark |
| 5 | 2 | Martin | Doe | 1 | 2 | Danielle/Charles/Martin |
| 8 | 5 | Katy | Perry | 1 | 3 | Danielle/Charles/Martin/Katy |
| 7 | 5 | Leo | Messi | 1 | 3 | Danielle/Charles/Martin/Leo |
| 9 | 7 | Alex | Doe | 1 | 4 | Danielle/Charles/Martin/Leo/Alex |
| 10 | 7 | Laureen | Doe | 1 | 4 | Danielle/Charles/Martin/Leo/Laureen |
| 3 | 1 | Michelle | Doe | 1 | 1 | Danielle/Michelle |
+------+-----------+-----------+----------+--------+-------+-------------------------------------+
我试图做一个嵌套的 select 但它没有用。在每条记录中包含儿童总数的最佳方法是什么?
预期结果:
+------+-----------+-----------+----------+--------+-------+-------------------------------------+---------------+
| PLID | SPONSORID | FIRSTNAME | LASTNAME | STATUS | LEVEL | PATH | TotalDownline |
+------+-----------+-----------+----------+--------+-------+-------------------------------------+---------------+
| 1 | 0 | Danielle | Lipsin | 1 | 0 | Danielle | 9 |
| 4 | 1 | Alissa | Doe | 1 | 1 | Danielle/Alissa | 0 |
| 2 | 1 | Charles | Doe | 1 | 1 | Danielle/Charles | 7 |
| 6 | 2 | Mark | Doe | 1 | 2 | Danielle/Charles/Mark | 0 |
| 5 | 2 | Martin | Doe | 1 | 2 | Danielle/Charles/Martin | 4 |
| 8 | 5 | Katy | Perry | 1 | 3 | Danielle/Charles/Martin/Katy | 0 |
| 7 | 5 | Leo | Messi | 1 | 3 | Danielle/Charles/Martin/Leo | 2 |
| 9 | 7 | Alex | Doe | 1 | 4 | Danielle/Charles/Martin/Leo/Alex | 0 |
| 10 | 7 | Laureen | Doe | 1 | 4 | Danielle/Charles/Martin/Leo/Laureen | 0 |
| 3 | 1 | Michelle | Doe | 1 | 1 | Danielle/Michelle | 0 |
+------+-----------+-----------+----------+--------+-------+-------------------------------------+---------------+
谢谢。
CREATE TABLE TEST (
PLID int,
sponsorid int,
firstname nvarchar(50),
lastname nvarchar(50),
status int
);
INSERT INTO TEST VALUES (1,0,'Danielle', 'Lipsin', 1);
INSERT INTO TEST VALUES (2,1,'Charles', 'Doe', 1);
INSERT INTO TEST VALUES (3,1,'Michelle', 'Doe', 1);
INSERT INTO TEST VALUES (4,1,'Alissa', 'Doe', 1);
INSERT INTO TEST VALUES (5,2,'Martin', 'Doe', 1);
INSERT INTO TEST VALUES (6,2,'Mark', 'Doe', 1);
INSERT INTO TEST VALUES (7,5,'Leo', 'Messi', 1);
INSERT INTO TEST VALUES (8,5,'Katy', 'Perry', 1);
INSERT INTO TEST VALUES (9,7,'Alex', 'Doe', 1);
INSERT INTO TEST VALUES (10,7,'Laureen', 'Doe', 1);
好的,您可以采用一种可能的方式,但不确定这是最好的方式。
- 根据与现有
path
(名称)相同的原则创建一个新列pathid
,但每个人都是唯一的。 - 通过对 CTE 使用子查询,计算
id
在pathid
中出现的次数,而不是我们的。
WITH cte1 (PLID, sponsorid, firstname, lastname, [Status], [LEVEL], [path], pathid) AS (
SELECT PLID, sponsorid, firstname, lastname, [Status], 0 AS [LEVEL]
, CAST(firstname AS VARCHAR(1000)) AS [path]
, CAST('/' + CAST(PLID AS varchar(38)) AS varchar(max)) AS pathid
FROM #TEST
WHERE PLID = 1--94
UNION ALL
SELECT c.PLID, c.sponsorid, c.firstname, c.lastname, c.[Status], cte1.[LEVEL] + 1 AS [LEVEL]
, CAST((cte1.[path] + '/' + c.firstname) AS VARCHAR(1000)) AS [path]
, CAST(cte1.pathid + '/' + cast(c.PLID AS varchar(38)) AS varchar(max)) AS pathid
FROM #TEST c
INNER JOIN cte1 ON c.sponsorid = cte1.plid
)
SELECT PLID, sponsorid, firstname, lastname, [Status], [LEVEL], [path], pathid
, (select count(*) from cte1 B where B.pathid + '/' like '%/' + cast(A.PLID AS varchar(38)) + '/%' and B.PLID <> A.PLID)
FROM cte1 A
ORDER BY [path] ASC;
Returns 您的示例数据:
PLID | sponsorid | firstname | lastname | Status | LEVEL | path | pathid | Total Downline |
---|---|---|---|---|---|---|---|---|
1 | 0 | Danielle | Lipsin | 1 | 0 | Danielle | /1 | 9 |
4 | 1 | Alissa | Doe | 1 | 1 | Danielle/Alissa | /1/4 | 0 |
2 | 1 | Charles | Doe | 1 | 1 | Danielle/Charles | /1/2 | 6 |
6 | 2 | Mark | Doe | 1 | 2 | Danielle/Charles/Mark | /1/2/6 | 0 |
5 | 2 | Martin | Doe | 1 | 2 | Danielle/Charles/Martin | /1/2/5 | 4 |
8 | 5 | Katy | Perry | 1 | 3 | Danielle/Charles/Martin/Katy | /1/2/5/8 | 0 |
7 | 5 | Leo | Messi | 1 | 3 | Danielle/Charles/Martin/Leo | /1/2/5/7 | 2 |
9 | 7 | Alex | Doe | 1 | 4 | Danielle/Charles/Martin/Leo/Alex | /1/2/5/7/9 | 0 |
10 | 7 | Laureen | Doe | 1 | 4 | Danielle/Charles/Martin/Leo/Laureen | /1/2/5/7/10 | 0 |
3 | 1 | Michelle | Doe | 1 | 1 | Danielle/Michelle | /1/3 | 0 |