假设我有以下表格:
表帐户:

parent_id | id

......
10         | 101
20         | 201
30         | 301
30         | 302
40         | 401
40         | 402
401        | 4011
401        | 4012
4012       | 40121

以及表帐户树:
ancestor | descentant | depth

1         | 10         | 1
1         | 20         | 1
1         | 30         | 1
1         | 40         | 1
1         | 101        | 2
1         | 201        | 2
1         | 301        | 2
1         | 302        | 2
1         | 401        | 2
1         | 402        | 2
1         | 4011       | 3
1         | 4012       | 3
1         | 40121      | 4
10        | 101        | 1
20        | 201        | 1
30        | 301        | 1
30        | 302        | 1
40        | 401        | 1
40        | 402        | 1
40        | 4011       | 2
40        | 4012       | 2
40        | 40121      | 3
401       | 4011       | 1
401       | 4012       | 1
4012      | 40121      | 1

我需要的是显示帐户ID的(父母)及其所有孩子,并为每个孩子显示他们的孩子,按深度升序分组;
到目前为止,我使用:
SELECT
    a.parent_id,
    a.id,
    p.depth
FROM
    accounts a
    INNER JOIN account_tree p ON a.id = p.descendant
    WHERE
        p.ancestor = 1
        AND p.depth <= 4
    ORDER BY
        a.parent_id;

它将返回按父ID排序的所有帐户。
我的期望是:
parent_id | id        | depth

1         | 10         | 1
10        | 101        | 2
1         | 20         | 1
20        | 201        | 2
1         | 30         | 1
30        | 301        | 2
30        | 302        | 2
1         | 40         | 1
40        | 401        | 2
401       | 4011       | 3
401       | 4012       | 3
4012      | 40121      | 4
40        | 402        | 2

我必须提到的是,在我正在进行的项目中,有500多个客户,他们的ID并不像我的例子中那样“可预测”编号,深度超过5层。

最佳答案

将tomc的答案改编成postgres

with recursive tree as (
    select parent_id, id, lpad(id::varchar(12),12,'0')::varchar(144) as idPath, 1::int as depth
    from accounts
    where parent_id = '1'
    union all
    select a.parent_id, a.id, concat(idPath, lpad(a.id,12,'0'))::varchar(144)  idPath, depth + 1::int as depth
    from accounts a
    join tree on tree.id=a.parent_id
)
select parent_id, id, depth, idpath
from tree
order by idpath

如果在任何级别上使用lpad()不同长度的帐户字符串,则不要偏向整体顺序。你需要选择适合你实际账号的长度。我使用了12,连接的路径需要是任意数字的倍数。
+----+-----------+-------+-------+--------------------------------------------------+
|    | parent_id | id    | depth | idpath                                           |
+----+-----------+-------+-------+--------------------------------------------------+
| 1  | 1         | 10    | 1     | 000000000010                                     |
| 2  | 10        | 101   | 2     | 000000000010000000000101                         |
| 3  | 1         | 20    | 1     | 000000000020                                     |
| 4  | 20        | 201   | 2     | 000000000020000000000201                         |
| 5  | 1         | 30    | 1     | 000000000030                                     |
| 6  | 30        | 301   | 2     | 000000000030000000000301                         |
| 7  | 30        | 302   | 2     | 000000000030000000000302                         |
| 8  | 1         | 40    | 1     | 000000000040                                     |
| 9  | 40        | 401   | 2     | 000000000040000000000401                         |
| 10 | 401       | 4011  | 3     | 000000000040000000000401000000004011             |
| 11 | 401       | 4012  | 3     | 000000000040000000000401000000004012             |
| 12 | 4012      | 40121 | 4     | 000000000040000000000401000000004012000000040121 |
| 13 | 40        | 402   | 2     | 000000000040000000000402                         |
+----+-----------+-------+-------+--------------------------------------------------+

使用的示例数据:
CREATE TABLE accounts(
   parent_id VARCHAR(12)
  ,id        VARCHAR(12)
);
INSERT INTO accounts(parent_id,id) VALUES ('1','10');
INSERT INTO accounts(parent_id,id) VALUES ('1','20');
INSERT INTO accounts(parent_id,id) VALUES ('1','30');
INSERT INTO accounts(parent_id,id) VALUES ('1','40');
INSERT INTO accounts(parent_id,id) VALUES ('10','101');
INSERT INTO accounts(parent_id,id) VALUES ('20','201');
INSERT INTO accounts(parent_id,id) VALUES ('30','301');
INSERT INTO accounts(parent_id,id) VALUES ('30','302');
INSERT INTO accounts(parent_id,id) VALUES ('40','401');
INSERT INTO accounts(parent_id,id) VALUES ('40','402');
INSERT INTO accounts(parent_id,id) VALUES ('401','4011');
INSERT INTO accounts(parent_id,id) VALUES ('401','4012');
INSERT INTO accounts(parent_id,id) VALUES ('4012','40121');

关于sql - PostgreSQL查询以按深度排序检索所有 child 的 parent ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53054640/

10-14 15:16