【问题标题】:Recursive SQL query (parent-child) to include total downline records per record递归 SQL 查询(父子)以包括每条记录的总下线记录
【发布时间】:2021-09-28 20:57:06
【问题描述】:

我有一个具有父子结构的表。

我设法通过使用代理的名字创建一个名为“路径”的字段来对这个结构进行排序,所以这个查询:

  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

...返回这个,树视图数据:

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

我尝试进行嵌套选择,但没有成功。在每条记录中包含儿童总数的最佳方法是什么?

预期结果:

+------+-----------+-----------+----------+--------+-------+-------------------------------------+---------------+
| 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);

【问题讨论】:

  • 你好戴尔。那你要我删除图片吗?请允许我几分钟,这样我就可以做得很好。谢谢。
  • 完成了,戴尔 :) 祝你玩得开心。
  • 请提供查询以创建表并插入一些示例数据。另外我们需要预期的结果集根据样本数据。
  • 不是真的 Dale,因为在那个例子中,他们正在查询第二个表(销售),我应该在其中对每条记录进行递归查询,以获得同一张表上每个代理的总下线(递归递归表的计数),这就是我努力的地方。换句话说,我不仅需要直接下线的记录计数,还需要下线的下线。我不知道我是否清楚地解释了它。我考虑过为每条记录创建一个循环和一个新查询,但这会使服务器崩溃(超过 25,000 个代理)。
  • 我在上面,戴尔。抱歉,在与我的老板打交道时试图让这个 Q 正确。我在上面。

标签: sql sql-server tsql recursive-query


【解决方案1】:

好的,你可以通过一种可能的方式做到这一点,但完全不确定它是最好的方式。

  1. 根据与现有path(姓名)相同的原则创建一个新列pathid,但每个人都是唯一的。
  2. 使用针对 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;

返回您的样本数据:

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

【讨论】:

  • 我试图先了解查询 Dale。我会在几分钟内尝试一下。我想先了解一下。谢谢。
  • 它工作得很好,但我试图了解你是如何完成它的,哈哈。谢谢戴尔。
  • 您可以更好地看到它在路径列上的作用,因为您可以看到名称 - 您不能使用它,因为名称永远不会是唯一的。因此,如果您使用“Charles”(“Danielle”太明显了),那么它会忽略自身并计算路径列中有多少其他行有“Charles”(当然它使用的是 ID 而不是名称)。很明显,查尔斯在他们之后又出现了 6 次。它对每一行都这样做 - 所以它不会很好地执行,它必须为每一行做一个子查询。
  • 哇,太聪明了。我现在明白了。非常感谢,我为此苦苦挣扎了将近两天。非常感谢。
  • 戴尔,查询处理 25,492 条记录耗时不到 2 秒。太棒了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-02
  • 1970-01-01
  • 1970-01-01
  • 2011-04-25
  • 1970-01-01
  • 2016-04-16
相关资源
最近更新 更多