PostgreSQL เด†เดจเตเดฑเดฟเดชเดพเดฑเตเดฑเต‡เดฃเตเด•เตพ: เดฎเตเดฏเตฝ เดฆเตเดตเดพเดฐเดคเตเดคเดฟเดจเต เดŽเดคเตเดฐ เด†เดดเดฎเตเดฃเตเดŸเต? เดจเดฎเตเด•เตเด•เต เดถเตเดฐเต‡เดฃเดฟเดฏเดฟเดฒเต‚เดŸเต† เดชเต‹เด•เดพเด‚

เดธเด™เตเด•เต€เตผเดฃเตเดฃเดฎเดพเดฏ ERP เดธเดฟเดธเตเดฑเตเดฑเด™เตเด™เดณเดฟเตฝ เดชเดฒ เดŽเดจเตเดฑเดฟเดฑเตเดฑเดฟเด•เตพเด•เตเด•เตเด‚ เด’เดฐเต เดถเตเดฐเต‡เดฃเดฟ เดธเตเดตเดญเดพเดตเดฎเตเดฃเตเดŸเตเดเด•เดคเดพเดจเดฎเดพเดฏ เดตเดธเตเดคเตเด•เตเด•เตพ เด…เดฃเดฟเดจเดฟเดฐเด•เตเด•เตเดฎเตเดชเต‹เตพ เดชเต‚เตผเดตเดฟเด•เดฐเตเด‚ เดชเดฟเตปเด—เดพเดฎเดฟเด•เดณเตเด‚ เดคเดฎเตเดฎเดฟเดฒเตเดณเตเดณ เดฌเดจเตเดงเดคเตเดคเดฟเดจเตเดฑเต† เดตเตƒเด•เตเดทเด‚ - เด‡เดคเดพเดฃเต เดŽเดจเตเดฑเตผเดชเตเดฐเตˆเดธเดธเดฟเดจเตเดฑเต† เดธเด‚เด˜เดŸเดจเดพ เด˜เดŸเดจ (เดˆ เดŽเดฒเตเดฒเดพ เดถเดพเด–เด•เดณเตเด‚ เดตเด•เตเดชเตเดชเตเด•เดณเตเด‚ เดตเตผเด•เตเด•เต เด—เตเดฐเต‚เดชเตเดชเตเด•เดณเตเด‚), เด•เต‚เดŸเดพเดคเต† เดšเดฐเด•เตเด•เตเด•เดณเตเดŸเต† เด•เดพเดฑเตเดฑเดฒเต‹เด—เต, เดœเต‹เดฒเดฟเดฏเตเดŸเต† เดฎเต‡เด–เดฒเด•เตพ, เดธเต†เดฏเดฟเตฝเดธเต เดชเต‹เดฏเดฟเดจเตเดฑเตเด•เดณเตเดŸเต† เดญเต‚เดฎเดฟเดถเดพเดธเตเดคเตเดฐเด‚,...

PostgreSQL เด†เดจเตเดฑเดฟเดชเดพเดฑเตเดฑเต‡เดฃเตเด•เตพ: เดฎเตเดฏเตฝ เดฆเตเดตเดพเดฐเดคเตเดคเดฟเดจเต เดŽเดคเตเดฐ เด†เดดเดฎเตเดฃเตเดŸเต? เดจเดฎเตเด•เตเด•เต เดถเตเดฐเต‡เดฃเดฟเดฏเดฟเดฒเต‚เดŸเต† เดชเต‹เด•เดพเด‚

เดตเดพเดธเตเดคเดตเดคเตเดคเดฟเตฝ, เด’เดจเตเดจเตเดฎเดฟเดฒเตเดฒ เดฌเดฟเดธเดฟเดจเดธเตเดธเต เด“เดŸเตเดŸเต‹เดฎเต‡เดทเตป เดฎเต‡เด–เดฒเด•เตพ, เดซเดฒเดฎเดพเดฏเดฟ เด’เดฐเต เดถเตเดฐเต‡เดฃเดฟเดฏเตเด‚ เด‰เดฃเตเดŸเดพเด•เดฟเดฒเตเดฒ. เดŽเดจเตเดจเดพเตฝ เดจเดฟเด™เตเด™เตพ "เดฌเดฟเดธเดฟเดจเดธเดฟเดจเดพเดฏเดฟ" เดชเตเดฐเดตเตผเดคเตเดคเดฟเด•เตเด•เตเดจเตเดจเดฟเดฒเตเดฒเต†เด™เตเด•เดฟเดฒเตเด‚, เดจเดฟเด™เตเด™เตพเด•เตเด•เต เด‡เดชเตเดชเต‹เดดเตเด‚ เดถเตเดฐเต‡เดฃเดฟเดชเดฐเดฎเดพเดฏ เดฌเดจเตเดงเด™เตเด™เตพ เดŽเดณเตเดชเตเดชเดคเตเดคเดฟเตฝ เดจเต‡เดฐเดฟเดŸเดพเตป เด•เดดเดฟเดฏเตเด‚. เด‡เดคเต เดจเดฟเดธเตเดธเดพเดฐเดฎเดพเดฃเต, เดจเดฟเด™เตเด™เดณเตเดŸเต† เดซเดพเดฎเดฟเดฒเดฟ เดŸเตเดฐเต€ เด…เดฒเตเดฒเต†เด™เตเด•เดฟเตฝ เดทเต‹เดชเตเดชเดฟเด‚เด—เต เดธเต†เดจเตเดฑเดฑเดฟเดฒเต† เดซเตเดฒเต‹เตผ เดชเตเดฒเดพเตป เดชเต‹เดฒเตเด‚ เด’เดฐเต‡ เด˜เดŸเดจเดฏเดพเดฃเต.

เด…เดคเตเดคเดฐเดฎเตŠเดฐเต เดฎเดฐเด‚ เด’เดฐเต เดกเดฟเดฌเดฟเดŽเด‚เดŽเดธเดฟเตฝ เดธเด‚เดญเดฐเดฟเด•เตเด•เตเดจเตเดจเดคเดฟเดจเต เดจเดฟเดฐเดตเดงเดฟ เดฎเดพเตผเด—เด™เตเด™เดณเตเดฃเตเดŸเต, เดŽเดจเตเดจเดพเตฝ เด‡เดจเตเดจเต เดžเด™เตเด™เตพ เด’เดฐเต เด“เดชเตเดทเดจเดฟเตฝ เดฎเดพเดคเตเดฐเด‚ เดถเตเดฐเดฆเตเดง เด•เต‡เดจเตเดฆเตเดฐเต€เด•เดฐเดฟเด•เตเด•เตเด‚:

CREATE TABLE hier(
  id
    integer
      PRIMARY KEY
, pid
    integer
      REFERENCES hier
, data
    json
);

CREATE INDEX ON hier(pid); -- ะฝะต ะทะฐะฑั‹ะฒะฐะตะผ, ั‡ั‚ะพ FK ะฝะต ะฟะพะดั€ะฐะทัƒะผะตะฒะฐะตั‚ ะฐะฒั‚ะพัะพะทะดะฐะฝะธะต ะธะฝะดะตะบัะฐ, ะฒ ะพั‚ะปะธั‡ะธะต ะพั‚ PK

เดจเดฟเด™เตเด™เตพ เดถเตเดฐเต‡เดฃเดฟเดฏเตเดŸเต† เด†เดดเด™เตเด™เดณเดฟเดฒเต‡เด•เตเด•เต เด‰เดฑเตเดฑเตเดจเต‹เด•เตเด•เตเดฎเตเดชเต‹เตพ, เด…เดคเตเดคเดฐเดฎเตŠเดฐเต เด˜เดŸเดจเดฏเดฟเตฝ เดจเดฟเด™เตเด™เดณเตเดŸเต† "เดจเดฟเดทเตโ€Œเด•เดณเด™เตเด•" เดฐเต€เดคเดฟเด•เตพ เดŽเดคเตเดฐเดคเตเดคเต‹เดณเด‚ เดซเดฒเดชเตเดฐเดฆเดฎเดพเด•เตเดฎเต†เดจเตเดจเต เด•เดพเดฃเดพเตป เด…เดคเต เด•เตเดทเดฎเดฏเต‹เดŸเต† เด•เดพเดคเตเดคเดฟเดฐเดฟเด•เตเด•เตเดจเตเดจเต.

PostgreSQL เด†เดจเตเดฑเดฟเดชเดพเดฑเตเดฑเต‡เดฃเตเด•เตพ: เดฎเตเดฏเตฝ เดฆเตเดตเดพเดฐเดคเตเดคเดฟเดจเต เดŽเดคเตเดฐ เด†เดดเดฎเตเดฃเตเดŸเต? เดจเดฎเตเด•เตเด•เต เดถเตเดฐเต‡เดฃเดฟเดฏเดฟเดฒเต‚เดŸเต† เดชเต‹เด•เดพเด‚
เด‰เดฃเตเดŸเดพเด•เตเดจเตเดจ เดธเดพเดงเดพเดฐเดฃ เดชเตเดฐเดถเตเดจเด™เตเด™เตพ, SQL-เตฝ เด…เดต เดจเดŸเดชเตเดชเดฟเดฒเดพเด•เตเด•เตเดจเตเดจเดคเต, เด…เดตเดฏเตเดŸเต† เดชเตเดฐเด•เดŸเดจเด‚ เดฎเต†เดšเตเดšเดชเตเดชเต†เดŸเตเดคเตเดคเดพเตป เดถเตเดฐเดฎเดฟเด•เตเด•เดพเด‚.

#1. เดฎเตเดฏเดฒเดฟเดจเตเดฑเต† เดฆเตเดตเดพเดฐเดคเตเดคเดฟเดจเตเดฑเต† เด†เดดเด‚ เดŽเดคเตเดฐเดฏเดพเดฃเต?

เดกเดฟเดชเตเดชเดพเตผเดŸเตเดŸเตโ€Œเดฎเต†เดจเตเดฑเตเด•เตพ, เดกเดฟเดตเดฟเดทเดจเตเด•เตพ, เดธเต†เด•เตเดŸเดฑเตเด•เตพ, เดฌเตเดฐเดพเดžเตเดšเตเด•เตพ, เดตเตผเด•เตเด•เดฟเด‚เด—เต เด—เตเดฐเต‚เดชเตเดชเตเด•เตพ ... - เดจเดฟเด™เตเด™เตพ เด…เดตเดฏเต† เดŽเดจเตเดคเต เดตเดฟเดณเดฟเดšเตเดšเดพเดฒเตเด‚, เดˆ เด˜เดŸเดจ เด“เตผเด—เดจเตˆเดธเต‡เดทเดจเตเดฑเต† เด˜เดŸเดจเดฏเดฟเตฝ เดตเด•เตเดชเตเดชเตเด•เดณเตเดŸเต† เด•เต€เดดเตเดตเดดเด•เตเด•เดคเตเดคเต† เดชเตเดฐเดคเดฟเดซเดฒเดฟเดชเตเดชเดฟเด•เตเด•เตเดฎเต†เดจเตเดจเต เดจเดฎเตเด•เตเด•เต เด‰เดฑเดชเตเดชเดพเดฏเดฟ เด…เด‚เด—เต€เด•เดฐเดฟเด•เตเด•เดพเด‚.
PostgreSQL เด†เดจเตเดฑเดฟเดชเดพเดฑเตเดฑเต‡เดฃเตเด•เตพ: เดฎเตเดฏเตฝ เดฆเตเดตเดพเดฐเดคเตเดคเดฟเดจเต เดŽเดคเตเดฐ เด†เดดเดฎเตเดฃเตเดŸเต? เดจเดฎเตเด•เตเด•เต เดถเตเดฐเต‡เดฃเดฟเดฏเดฟเดฒเต‚เดŸเต† เดชเต‹เด•เดพเด‚

เด†เดฆเตเดฏเด‚, เดจเดฎเตเด•เตเด•เต 10K เด˜เดŸเด•เด™เตเด™เดณเตเดŸเต† 'เดตเตƒเด•เตเดทเด‚' เดธเตƒเดทเตเดŸเดฟเด•เตเด•เดพเด‚

INSERT INTO hier
WITH RECURSIVE T AS (
  SELECT
    1::integer id
  , '{1}'::integer[] pids
UNION ALL
  SELECT
    id + 1
  , pids[1:(random() * array_length(pids, 1))::integer] || (id + 1)
  FROM
    T
  WHERE
    id < 10000
)
SELECT
  pids[array_length(pids, 1)] id
, pids[array_length(pids, 1) - 1] pid
FROM
  T;

เดเดฑเตเดฑเดตเตเด‚ เดฒเดณเดฟเดคเดฎเดพเดฏ เดœเต‹เดฒเดฟเดฏเดฟเตฝ เดจเดฟเดจเตเดจเต เดจเดฎเตเด•เตเด•เต เด†เดฐเด‚เดญเดฟเด•เตเด•เดพเด‚ - เด’เดฐเต เดชเตเดฐเดคเตเดฏเต‡เด• เดฎเต‡เด–เดฒเดฏเดฟเตฝ เดœเต‹เดฒเดฟ เดšเต†เดฏเตเดฏเตเดจเตเดจ เดŽเดฒเตเดฒเดพ เดœเต€เดตเดจเด•เตเด•เดพเดฐเต†เดฏเตเด‚ เด•เดฃเตเดŸเต†เดคเตเดคเตเด•, เด…เดฒเตเดฒเต†เด™เตเด•เดฟเตฝ เดถเตเดฐเต‡เดฃเดฟเดฏเตเดŸเต† เด…เดŸเดฟเดธเตเดฅเดพเดจเดคเตเดคเดฟเตฝ - เด’เดฐเต เดจเต‹เดกเดฟเดจเตเดฑเต† เดŽเดฒเตเดฒเดพ เด•เตเดŸเตเดŸเดฟเด•เดณเต†เดฏเตเด‚ เด•เดฃเตเดŸเต†เดคเตเดคเตเด•. เดชเดฟเตปเด—เดพเดฎเดฟเดฏเตเดŸเต† "เด†เดดเด‚" เดฒเดญเดฟเด•เตเด•เตเดจเตเดจเดคเต เดจเดจเตเดจเดพเดฏเดฟเดฐเดฟเด•เตเด•เตเด‚ ... เด‡เดคเต†เดฒเตเดฒเดพเด‚ เด†เดตเดถเตเดฏเดฎเดพเดฏเดฟ เดตเดจเตเดจเต‡เด•เตเด•เดพเด‚, เด‰เดฆเดพเดนเดฐเดฃเดคเตเดคเดฟเดจเต, เดเดคเต†เด™เตเด•เดฟเดฒเตเด‚ เดคเดฐเดคเตเดคเดฟเดฒเตเดณเตเดณ เดจเดฟเตผเดฎเตเดฎเดพเดฃเดคเตเดคเดฟเดจเต เดˆ เดœเต€เดตเดจเด•เตเด•เดพเดฐเตเดŸเต† เดเดกเดฟเด•เดณเตเดŸเต† เดฒเดฟเดธเตเดฑเตเดฑเต เด…เดŸเดฟเดธเตเดฅเดพเดจเดฎเดพเด•เตเด•เดฟเดฏเตเดณเตเดณ เดธเด™เตเด•เต€เตผเดฃเตเดฃเดฎเดพเดฏ เดคเดฟเดฐเดžเตเดžเต†เดŸเตเดชเตเดชเต.

เดˆ เดชเดฟเตปเด—เดพเดฎเดฟเด•เดณเตเดŸเต† เดฐเดฃเตเดŸเต เดฒเต†เดตเดฒเตเด•เตพ เดฎเดพเดคเตเดฐเดฎเต‡ เด‰เดณเตเดณเต‚เดตเต†เด™เตเด•เดฟเตฝ เดŽเดฒเตเดฒเดพเด‚ เดถเดฐเดฟเดฏเดพเด•เตเด‚, เดŽเดฃเตเดฃเด‚ เด’เดฐเต เดกเดธเดจเดฟเดจเตเดณเตเดณเดฟเตฝ เด†เดฃเต†เด™เตเด•เดฟเตฝ, เดŽเดจเตเดจเดพเตฝ 5 เดฒเต†เดตเดฒเดฟเตฝ เด•เต‚เดŸเตเดคเตฝ เด‰เดฃเตเดŸเต†เด™เตเด•เดฟเตฝ, เด‡เดคเดฟเดจเด•เด‚ เดกเดธเตป เด•เดฃเด•เตเด•เดฟเดจเต เดชเดฟเตปเด—เดพเดฎเดฟเด•เตพ เด‰เดฃเตเดŸเต†เด™เตเด•เดฟเตฝ, เดชเตเดฐเดถเตเดจเด™เตเด™เตพ เด‰เดฃเตเดŸเดพเด•เดพเด‚. เดชเดฐเดฎเตเดชเดฐเดพเด—เดค เดกเต—เตบ-เดฆเดฟ-เดŸเตเดฐเต€ เดธเต†เตผเดšเตเดšเต เด“เดชเตโ€Œเดทเดจเตเด•เตพ เดŽเด™เตเด™เดจเต†เดฏเดพเดฃเต เดŽเดดเตเดคเดชเตเดชเต†เดŸเตเดŸเดฟเดฐเดฟเด•เตเด•เตเดจเตเดจเดคเต (เด’เดชเตเดชเด‚ เดชเตเดฐเดตเตผเดคเตเดคเดฟเด•เตเด•เตเดจเตเดจเต) เดŽเดจเตเดจเต เดจเต‹เด•เตเด•เดพเด‚. เดŽเดจเตเดจเดพเตฝ เด†เดฆเตเดฏเด‚, เดžเด™เตเด™เดณเตเดŸเต† เด—เดตเต‡เดทเดฃเดคเตเดคเดฟเดจเต เดเดฑเตเดฑเดตเตเด‚ เดฐเดธเด•เดฐเดฎเดพเดฏ เดจเต‹เดกเตเด•เตพ เดเดคเต†เดจเตเดจเต เดจเดฎเตเด•เตเด•เต เดจเดฟเตผเดฃเตเดฃเดฏเดฟเด•เตเด•เดพเด‚.

เดเดฑเตเดฑเดตเตเด‚ เด•เต‚เดŸเตเดคเตฝ "เด†เดดเดฎเตเดณเตเดณ" เด‰เดชเดตเตƒเด•เตเดทเด™เตเด™เตพ:

WITH RECURSIVE T AS (
  SELECT
    id
  , pid
  , ARRAY[id] path
  FROM
    hier
  WHERE
    pid IS NULL
UNION ALL
  SELECT
    hier.id
  , hier.pid
  , T.path || hier.id
  FROM
    T
  JOIN
    hier
      ON hier.pid = T.id
)
TABLE T ORDER BY array_length(path, 1) DESC;

 id  | pid  | path
---------------------------------------------
7624 | 7623 | {7615,7620,7621,7622,7623,7624}
4995 | 4994 | {4983,4985,4988,4993,4994,4995}
4991 | 4990 | {4983,4985,4988,4989,4990,4991}
...

เดเดฑเตเดฑเดตเตเด‚ เด•เต‚เดŸเตเดคเตฝ "เดตเดฟเดถเดพเดฒเด‚" เด‰เดชเดตเตƒเด•เตเดทเด™เตเด™เตพ:

...
SELECT
  path[1] id
, count(*)
FROM
  T
GROUP BY
  1
ORDER BY
  2 DESC;

id   | count
------------
5300 |   30
 450 |   28
1239 |   27
1573 |   25

เดˆ เดšเต‹เดฆเตเดฏเด™เตเด™เตพเด•เตเด•เต เดžเด™เตเด™เตพ เดธเดพเดงเดพเดฐเดฃ เด‰เดชเดฏเต‹เด—เดฟเดšเตเดšเต เด†เดตเตผเดคเตเดคเดจ เดšเต‡เดฐเตฝ:
PostgreSQL เด†เดจเตเดฑเดฟเดชเดพเดฑเตเดฑเต‡เดฃเตเด•เตพ: เดฎเตเดฏเตฝ เดฆเตเดตเดพเดฐเดคเตเดคเดฟเดจเต เดŽเดคเตเดฐ เด†เดดเดฎเตเดฃเตเดŸเต? เดจเดฎเตเด•เตเด•เต เดถเตเดฐเต‡เดฃเดฟเดฏเดฟเดฒเต‚เดŸเต† เดชเต‹เด•เดพเด‚

เดตเตเดฏเด•เตเดคเดฎเดพเดฏเตเด‚, เดˆ เด…เดญเตเดฏเตผเดคเตเดฅเดจ เดฎเดพเดคเตƒเด•เดฏเดฟเตฝ เด†เดตเตผเดคเตเดคเดจเด™เตเด™เดณเตเดŸเต† เดŽเดฃเตเดฃเด‚ เดฎเตŠเดคเตเดคเด‚ เดชเดฟเตปเด—เดพเดฎเดฟเด•เดณเตเดŸเต† เดŽเดฃเตเดฃเดคเตเดคเดฟเดจเต เดคเตเดฒเตเดฏเดฎเดพเดฏเดฟเดฐเดฟเด•เตเด•เตเด‚ (เด…เดตเดฏเดฟเตฝ เดจเดฟเดฐเดตเดงเดฟ เดกเดธเตป เด‰เดฃเตเดŸเต), เด‡เดคเดฟเดจเต เดตเดณเดฐเต† เดชเตเดฐเดงเดพเดจเดชเตเดชเต†เดŸเตเดŸ เดตเดฟเดญเดตเด™เตเด™เตพ เดŽเดŸเตเด•เตเด•เดพเด‚, เด…เดคเดฟเดจเตเดฑเต† เดซเดฒเดฎเดพเดฏเดฟ เดธเดฎเดฏเด‚.

เดจเดฎเตเด•เตเด•เต "เดตเดฟเดถเดพเดฒเดฎเดพเดฏ" เด‰เดชเดตเตƒเด•เตเดทเด‚ เดชเดฐเดฟเดถเต‹เดงเดฟเด•เตเด•เดพเด‚:

WITH RECURSIVE T AS (
  SELECT
    id
  FROM
    hier
  WHERE
    id = 5300
UNION ALL
  SELECT
    hier.id
  FROM
    T
  JOIN
    hier
      ON hier.pid = T.id
)
TABLE T;

PostgreSQL เด†เดจเตเดฑเดฟเดชเดพเดฑเตเดฑเต‡เดฃเตเด•เตพ: เดฎเตเดฏเตฝ เดฆเตเดตเดพเดฐเดคเตเดคเดฟเดจเต เดŽเดคเตเดฐ เด†เดดเดฎเตเดฃเตเดŸเต? เดจเดฎเตเด•เตเด•เต เดถเตเดฐเต‡เดฃเดฟเดฏเดฟเดฒเต‚เดŸเต† เดชเต‹เด•เดพเด‚
[explain.tensor.ru-เตฝ เด•เดพเดฃเตเด•]

เดชเตเดฐเดคเต€เด•เตเดทเดฟเดšเตเดšเดคเตเดชเต‹เดฒเต†, เดžเด™เตเด™เตพ 30 เดฑเต†เด•เตเด•เต‹เตผเดกเตเด•เดณเตเด‚ เด•เดฃเตเดŸเต†เดคเตเดคเดฟ. เดŽเดจเตเดจเดพเตฝ เด…เดตเตผ เดฎเตŠเดคเตเดคเด‚ เดธเดฎเดฏเดคเตเดคเดฟเดจเตเดฑเต† 60% เด‡เดคเดฟเดจเดพเดฏเดฟ เดšเต†เดฒเดตเดดเดฟเดšเตเดšเต - เด•เดพเดฐเดฃเด‚ เด…เดตเตผ เดธเต‚เดšเดฟเด•เดฏเดฟเตฝ 30 เดคเดฟเดฐเดฏเดฒเตเด•เดณเตเด‚ เดจเดŸเดคเตเดคเดฟ. เด•เตเดฑเดšเตเดšเตเด•เต‚เดŸเดฟ เดšเต†เดฏเตเดฏเดพเตป เดชเดฑเตเดฑเตเดฎเต‹?

เดธเต‚เดšเดฟเด• เดชเตเดฐเด•เดพเดฐเด‚ เดฌเตพเด•เตเด•เต เดชเตเดฐเต‚เดซเต เดฑเต€เดกเดฟเด‚เด—เต

เด“เดฐเต‹ เดจเต‹เดกเดฟเดจเตเด‚ เด’เดฐเต เดชเตเดฐเดคเตเดฏเต‡เด• เดธเต‚เดšเดฟเด• เด…เดจเตเดตเต‡เดทเดฃเด‚ เดจเดŸเดคเตเดคเต‡เดฃเตเดŸเดคเตเดฃเตเดŸเต‹? เด‡เดฒเตเดฒ เดŽเดจเตเดจเต เดฎเดพเดฑเตเดจเตเดจเต - เดจเดฎเตเด•เตเด•เต เดธเต‚เดšเดฟเด•เดฏเดฟเตฝ เดจเดฟเดจเตเดจเต เดตเดพเดฏเดฟเด•เตเด•เดพเด‚ เด’เดฐเต เด•เต‹เดณเดฟเตฝ เด’เดฐเต‡เดธเดฎเดฏเด‚ เดจเดฟเดฐเดตเดงเดฟ เด•เต€เด•เตพ เด‰เดชเดฏเต‹เด—เดฟเด•เตเด•เตเดจเตเดจเต เดธเดนเดพเดฏเดคเตเดคเต‹เดŸเต† = ANY(array).

เด…เดคเตเดคเดฐเดคเตเดคเดฟเดฒเตเดณเตเดณ เด“เดฐเต‹ เดเดกเดจเตเดฑเดฟเดซเดฏเดฑเตเด•เดณเดฟเดฒเตเด‚ เดจเดฎเตเด•เตเด•เต เดฎเตเดฎเตเดชเดคเตเดคเต† เด˜เดŸเตเดŸเดคเตเดคเดฟเตฝ เด•เดฃเตเดŸเต†เดคเตเดคเดฟเดฏ เดŽเดฒเตเดฒเดพ เดเดกเดฟเด•เดณเตเด‚ "เดจเต‹เดกเตเด•เตพ" เด‰เดชเดฏเต‹เด—เดฟเดšเตเดšเต เดŽเดŸเตเด•เตเด•เดพเด‚. เด…เดคเดพเดฏเดคเต, เด“เดฐเต‹ เด…เดŸเตเดคเตเดค เด˜เดŸเตเดŸเดคเตเดคเดฟเดฒเตเด‚ เดžเด™เตเด™เตพ เดšเต†เดฏเตเดฏเตเด‚ เด’เดฐเต เดจเดฟเดถเตเดšเดฟเดค เดคเดฒเดคเตเดคเดฟเดฒเตเดณเตเดณ เดŽเดฒเตเดฒเดพ เดชเดฟเตปเด—เดพเดฎเดฟเด•เดณเต†เดฏเตเด‚ เด’เดฐเต‡เดธเดฎเดฏเด‚ เดคเดฟเดฐเดฏเตเด•.

เด‡เดตเดฟเดŸเต† เดฎเดพเดคเตเดฐเดฎเดพเดฃเต เดชเตเดฐเดถเตเดจเด‚, เด†เดตเตผเดคเตเดคเดจ เดคเดฟเดฐเดžเตเดžเต†เดŸเตเดชเตเดชเดฟเตฝ, เด’เดฐเต เดจเต†เดธเตเดฑเตเดฑเดกเต เด…เดจเตเดตเต‡เดทเดฃเดคเตเดคเดฟเตฝ เดจเดฟเด™เตเด™เตพเด•เตเด•เต เดธเตเดตเดฏเด‚ เด†เด•เตเดธเดธเต เดšเต†เดฏเตเดฏเดพเตป เด•เดดเดฟเดฏเดฟเดฒเตเดฒ, เดŽเดจเตเดจเดพเตฝ เดฎเตเดฎเตเดชเดคเตเดคเต† เดฒเต†เดตเดฒเดฟเตฝ เด•เดฃเตเดŸเต†เดคเตเดคเดฟเดฏเดต เดฎเดพเดคเตเดฐเด‚ เดžเด™เตเด™เตพ เดŽเด™เตเด™เดจเต†เดฏเต†เด™เตเด•เดฟเดฒเตเด‚ เดคเดฟเดฐเดžเตเดžเต†เดŸเตเด•เตเด•เต‡เดฃเตเดŸเดคเตเดฃเตเดŸเต... เดฎเตเดดเตเดตเตป เดคเดฟเดฐเดžเตเดžเต†เดŸเตเดชเตเดชเดฟเดจเตเด‚ เด’เดฐเต เดจเต†เดธเตเดฑเตเดฑเดกเต เด…เดจเตเดตเต‡เดทเดฃเด‚ เดจเดŸเดคเตเดคเตเดจเตเดจเดคเต เด…เดธเดพเดงเตเดฏเดฎเดพเดฃเต†เดจเตเดจเต เด‡เดคเต เดฎเดพเดฑเตเดจเตเดจเต, เดชเด•เตเดทเต‡ เด…เดคเดฟเดจเตเดฑเต† เดจเดฟเตผเดฆเตเดฆเดฟเดทเตเดŸ เดซเต€เตฝเดกเดฟเดจเต เด‡เดคเต เดธเดพเดงเตเดฏเดฎเดพเดฃเต. เดˆ เดซเต€เตฝเดกเตเด‚ เด’เดฐเต เด…เดฑเต‡ เด†เด•เดพเด‚ - เด…เดคเดพเดฃเต เดจเดฎเตเดฎเตพ เด‰เดชเดฏเต‹เด—เดฟเด•เตเด•เต‡เดฃเตเดŸเดคเต ANY.

เด‡เดคเต เด…เตฝเดชเตเดชเด‚ เดญเตเดฐเดพเดจเตเดคเดพเดฃเต†เดจเตเดจเต เดคเต‹เดจเตเดจเตเดจเตเดจเต, เดชเด•เตเดทเต‡ เดกเดฏเด—เตเดฐเดพเดฎเดฟเตฝ เดŽเดฒเตเดฒเดพเด‚ เดฒเดณเดฟเดคเดฎเดพเดฃเต.

PostgreSQL เด†เดจเตเดฑเดฟเดชเดพเดฑเตเดฑเต‡เดฃเตเด•เตพ: เดฎเตเดฏเตฝ เดฆเตเดตเดพเดฐเดคเตเดคเดฟเดจเต เดŽเดคเตเดฐ เด†เดดเดฎเตเดฃเตเดŸเต? เดจเดฎเตเด•เตเด•เต เดถเตเดฐเต‡เดฃเดฟเดฏเดฟเดฒเต‚เดŸเต† เดชเต‹เด•เดพเด‚

WITH RECURSIVE T AS (
  SELECT
    ARRAY[id] id$
  FROM
    hier
  WHERE
    id = 5300
UNION ALL
  SELECT
    ARRAY(
      SELECT
        id
      FROM
        hier
      WHERE
        pid = ANY(T.id$)
    ) id$
  FROM
    T
  WHERE
    coalesce(id$, '{}') <> '{}' -- ัƒัะปะพะฒะธะต ะฒั‹ั…ะพะดะฐ ะธะท ั†ะธะบะปะฐ - ะฟัƒัั‚ะพะน ะผะฐััะธะฒ
)
SELECT
  unnest(id$) id
FROM
  T;

PostgreSQL เด†เดจเตเดฑเดฟเดชเดพเดฑเตเดฑเต‡เดฃเตเด•เตพ: เดฎเตเดฏเตฝ เดฆเตเดตเดพเดฐเดคเตเดคเดฟเดจเต เดŽเดคเตเดฐ เด†เดดเดฎเตเดฃเตเดŸเต? เดจเดฎเตเด•เตเด•เต เดถเตเดฐเต‡เดฃเดฟเดฏเดฟเดฒเต‚เดŸเต† เดชเต‹เด•เดพเด‚
[explain.tensor.ru-เตฝ เด•เดพเดฃเตเด•]

เด‡เดตเดฟเดŸเต† เดเดฑเตเดฑเดตเตเด‚ เดชเตเดฐเดงเดพเดจเดชเตเดชเต†เดŸเตเดŸ เด•เดพเดฐเตเดฏเด‚ เดชเต‹เดฒเตเด‚ เด…เดฒเตเดฒ เด•เตƒเดคเตเดฏเดธเดฎเดฏเดคเตเดคเต 1.5 เดคเดตเดฃ เดตเดฟเดœเดฏเดฟเด•เตเด•เตเด•เดธเต‚เดšเดฟเด•เดฏเดฟเดฒเต‡เด•เตเด•เต 5 เด•เต‹เดณเตเด•เตพเด•เตเด•เต เดชเด•เดฐเด‚ 30 เด•เต‹เดณเตเด•เตพ เดฎเดพเดคเตเดฐเดฎเต‡ เด‰เดณเตเดณเต‚ เดŽเดจเตเดจเดคเดฟเดจเดพเตฝ, เดžเด™เตเด™เตพ เด•เตเดฑเดšเตเดšเต เดฌเดซเดฑเตเด•เตพ เด•เตเดฑเดšเตเดšเดฟเดŸเตเดŸเตเดฃเตเดŸเต!

เด…เดจเตเดคเดฟเดฎ เด…เตบเดจเต†เดธเตเดฑเตเดฑเดฟเดจเต เดถเต‡เดทเดตเตเด‚, เดเดกเดจเตเดฑเดฟเดซเดฏเดฑเตเด•เตพ "เดฒเต†เดตเดฒเตเด•เตพ" เด…เดจเตเดธเดฐเดฟเดšเตเดšเต เด•เตเดฐเดฎเต€เด•เดฐเดฟเดšเตเดšเต เดคเตเดŸเดฐเตเด‚ เดŽเดจเตเดจเดคเดพเดฃเต เด’เดฐเต เด…เดงเดฟเด• เดฌเต‹เดฃเดธเต.

เดจเต‹เดกเต เดšเดฟเดนเตเดจเด‚

เดชเตเดฐเด•เดŸเดจเด‚ เดฎเต†เดšเตเดšเดชเตเดชเต†เดŸเตเดคเตเดคเดพเตป เดธเดนเดพเดฏเดฟเด•เตเด•เตเดจเตเดจ เด…เดŸเตเดคเตเดค เดชเดฐเดฟเด—เดฃเดจ -- "เด‡เดฒเด•เตพเด•เตเด•เต" เด•เตเดŸเตเดŸเดฟเด•เดณเตเดฃเตเดŸเดพเด•เดฟเดฒเตเดฒ, เด…เดคเดพเดฏเดคเต, เด…เดตเตผเด•เตเด•เต "เดคเดพเดดเต‡เด•เตเด•เต" เดจเต‹เด•เตเด•เต‡เดฃเตเดŸ เด†เดตเดถเตเดฏเดฎเดฟเดฒเตเดฒ. เดžเด™เตเด™เดณเตเดŸเต† เดšเตเดฎเดคเดฒเดฏเตเดŸเต† เดฐเต‚เดชเต€เด•เดฐเดฃเดคเตเดคเดฟเตฝ, เด‡เดคเดฟเดจเตผเดคเตเดฅเด‚ เดžเด™เตเด™เตพ เดตเด•เตเดชเตเดชเตเด•เดณเตเดŸเต† เดถเตƒเด‚เด–เดฒ เดชเดฟเดจเตเดคเตเดŸเดฐเตเด•เดฏเตเด‚ เด’เดฐเต เดœเต€เดตเดจเด•เตเด•เดพเดฐเดจเดฟเตฝ เดŽเดคเตเดคเตเด•เดฏเตเด‚ เดšเต†เดฏเตเดคเดพเตฝ, เดˆ เดถเดพเด–เดฏเดฟเตฝ เด•เต‚เดŸเตเดคเตฝ เดจเต‹เด•เตเด•เต‡เดฃเตเดŸ เด†เดตเดถเตเดฏเดฎเดฟเดฒเตเดฒ เดŽเดจเตเดจเดพเดฃเต.

เดจเดฎเตเด•เตเด•เต เดจเดฎเตเดฎเตเดŸเต† เดฎเต‡เดถเดฏเดฟเดฒเต‡เด•เตเด•เต เด•เดŸเด•เตเด•เดพเด‚ เด…เดงเดฟเด• boolean-เดซเต€เตฝเดกเต, เดจเดฎเตเดฎเตเดŸเต† เดŸเตเดฐเต€เดฏเดฟเดฒเต† เดˆ เดชเตเดฐเดคเตเดฏเต‡เด• เดŽเตปเดŸเตเดฐเดฟ เด’เดฐเต "เดจเต‹เดกเต" เด†เดฃเต‹ - เด…เดคเดพเดฏเดคเต, เด…เดคเดฟเดจเต เดธเดจเตเดคเดคเดฟเด•เตพ เด‰เดฃเตเดŸเดพเด•เตเดฎเต‹ เดŽเดจเตเดจเต เด…เดคเต เด‰เดŸเตป เดคเดจเตเดจเต† เดžเด™เตเด™เดณเต‹เดŸเต เดชเดฑเดฏเตเด‚.

ALTER TABLE hier
  ADD COLUMN branch boolean;

UPDATE
  hier T
SET
  branch = TRUE
WHERE
  EXISTS(
    SELECT
      NULL
    FROM
      hier
    WHERE
      pid = T.id
    LIMIT 1
);
-- ะ—ะฐะฟั€ะพั ัƒัะฟะตัˆะฝะพ ะฒั‹ะฟะพะปะฝะตะฝ: 3033 ัั‚ั€ะพะบ ะธะทะผะตะฝะตะฝะพ ะทะฐ 42 ะผั.

เด•เตŠเดณเตเดณเดพเด‚! เดŽเดฒเตเดฒเดพ เดตเตƒเด•เตเดท เดฎเต‚เดฒเด•เด™เตเด™เดณเดฟเดฒเตเด‚ 30% เตฝ เด•เต‚เดŸเตเดคเตฝ เดฎเดพเดคเตเดฐเดฎเต‡ เดชเดฟเตปเด—เดพเดฎเดฟเด•เดณเตเดณเตเดณเต‚เดตเต†เดจเตเดจเต เด‡เดคเต เดฎเดพเดฑเตเดจเตเดจเต.

เด‡เดชเตเดชเต‹เตพ เดจเดฎเตเด•เตเด•เต เด…เดฒเตเดชเด‚ เดตเตเดฏเดคเตเดฏเดธเตเดคเดฎเดพเดฏ เดฎเต†เด•เตเด•เดพเดจเดฟเด•เตเด•เต เด‰เดชเดฏเต‹เด—เดฟเด•เตเด•เดพเด‚ - เด†เดตเตผเดคเตเดคเดจ เดญเดพเด—เดคเตเดคเต‡เด•เตเด•เตเดณเตเดณ เด•เดฃเด•เตเดทเดจเตเด•เตพ LATERAL, เด†เดตเตผเดคเตเดคเดจ "เดชเดŸเตเดŸเดฟเด•" เดฏเตเดŸเต† เดซเต€เตฝเดกเตเด•เตพ เด‰เดŸเดจเดŸเดฟ เด†เด•เตเดธเดธเต เดšเต†เดฏเตเดฏเดพเตป เดžเด™เตเด™เดณเต† เด…เดจเตเดตเดฆเดฟเด•เตเด•เตเด•เดฏเตเด‚ เด•เต€เด•เดณเตเดŸเต† เดธเต†เดฑเตเดฑเต เด•เตเดฑเดฏเตเด•เตเด•เตเดจเตเดจเดคเดฟเดจเต เด’เดฐเต เดจเต‹เดกเต เด…เดŸเดฟเดธเตเดฅเดพเดจเดฎเดพเด•เตเด•เดฟเดฏเตเดณเตเดณ เดซเดฟเตฝเดŸเตเดŸเดฑเดฟเด‚เด—เต เด…เดตเดธเตเดฅเดฏเตเดณเตเดณ เด’เดฐเต เดฎเตŠเดคเตเดคเดคเตเดคเดฟเดฒเตเดณเตเดณ เดซเด‚เด—เตเดทเตป เด‰เดชเดฏเต‹เด—เดฟเด•เตเด•เตเด•เดฏเตเด‚ เดšเต†เดฏเตเดฏเตเด‚:

PostgreSQL เด†เดจเตเดฑเดฟเดชเดพเดฑเตเดฑเต‡เดฃเตเด•เตพ: เดฎเตเดฏเตฝ เดฆเตเดตเดพเดฐเดคเตเดคเดฟเดจเต เดŽเดคเตเดฐ เด†เดดเดฎเตเดฃเตเดŸเต? เดจเดฎเตเด•เตเด•เต เดถเตเดฐเต‡เดฃเดฟเดฏเดฟเดฒเต‚เดŸเต† เดชเต‹เด•เดพเด‚

WITH RECURSIVE T AS (
  SELECT
    array_agg(id) id$
  , array_agg(id) FILTER(WHERE branch) ns$
  FROM
    hier
  WHERE
    id = 5300
UNION ALL
  SELECT
    X.*
  FROM
    T
  JOIN LATERAL (
    SELECT
      array_agg(id) id$
    , array_agg(id) FILTER(WHERE branch) ns$
    FROM
      hier
    WHERE
      pid = ANY(T.ns$)
  ) X
    ON coalesce(T.ns$, '{}') <> '{}'
)
SELECT
  unnest(id$) id
FROM
  T;

PostgreSQL เด†เดจเตเดฑเดฟเดชเดพเดฑเตเดฑเต‡เดฃเตเด•เตพ: เดฎเตเดฏเตฝ เดฆเตเดตเดพเดฐเดคเตเดคเดฟเดจเต เดŽเดคเตเดฐ เด†เดดเดฎเตเดฃเตเดŸเต? เดจเดฎเตเด•เตเด•เต เดถเตเดฐเต‡เดฃเดฟเดฏเดฟเดฒเต‚เดŸเต† เดชเต‹เด•เดพเด‚
[explain.tensor.ru-เตฝ เด•เดพเดฃเตเด•]

เด’เดฐเต เดธเต‚เดšเดฟเด• เด•เต‹เตพ เด•เต‚เดŸเดฟ เด•เตเดฑเดฏเตเด•เตเด•เดพเตป เดžเด™เตเด™เตพเด•เตเด•เต เด•เดดเดฟเดžเตเดžเต เดตเต‹เดณเดฟเดฏเดคเตเดคเดฟเตฝ 2 เดคเดตเดฃเดฏเดฟเตฝ เด•เต‚เดŸเตเดคเตฝ เดตเดฟเดœเดฏเดฟเดšเตเดšเต เดชเตเดฐเต‚เดซเต เดฑเต€เดกเต.

#2. เดจเดฎเตเด•เตเด•เต เดตเต‡เดฐเตเด•เดณเดฟเดฒเต‡เด•เตเด•เต เดฎเดŸเด™เตเด™เดพเด‚

เดเดคเต เดธเต‹เดดเตโ€Œเดธเต เดทเต€เดฑเตเดฑเดฟเดจเต† (เดเดคเตŠเด•เตเด•เต† เดธเต‚เดšเด•เด™เตเด™เดณเต‹เดŸเต†) เดธเดพเดฎเตเดชเดฟเดณเดฟเตฝ เด‰เตพเดชเตเดชเต†เดŸเตเดคเตเดคเดฟ เดŽเดจเตเดจเดคเดฟเดจเต† เด•เตเดฑเดฟเดšเตเดšเตเดณเตเดณ เดตเดฟเดตเดฐเด™เตเด™เตพ เดจเดฟเดฒเดจเดฟเตผเดคเตเดคเดฟเด•เตเด•เตŠเดฃเตเดŸเต, "เดฎเดฐเดคเตเดคเดฟเดจเตเดฑเต† เดฎเตเด•เดณเดฟเดฒเตเดณเตเดณ" เดŽเดฒเตเดฒเดพ เด˜เดŸเด•เด™เตเด™เดณเตเดŸเต†เดฏเตเด‚ เดฑเต†เด•เตเด•เต‹เตผเดกเตเด•เตพ เดจเดฟเด™เตเด™เตพเด•เตเด•เต เดถเต‡เด–เดฐเดฟเด•เตเด•เดฃเดฎเต†เด™เตเด•เดฟเตฝ เดˆ เด…เตฝเด—เต‹เดฐเดฟเดคเด‚ เด‰เดชเดฏเต‹เด—เดชเตเดฐเดฆเดฎเดพเด•เตเด‚ - เด‰เดฆเดพเดนเดฐเดฃเดคเตเดคเดฟเดจเต, เด’เดฐเต เดธเด‚เด—เตเดฐเดน เดฑเดฟเดชเตเดชเต‹เตผเดŸเตเดŸเต เดธเตƒเดทเตเดŸเดฟเด•เตเด•เตเดจเตเดจเดคเดฟเดจเต เดจเต‹เดกเตเด•เดณเดฟเดฒเต‡เด•เตเด•เตเดณเตเดณ เด•เต‚เดŸเตเดŸเดฟเดšเตเดšเต‡เตผเด•เตเด•เดฒเดฟเดจเตŠเดชเตเดชเด‚.

PostgreSQL เด†เดจเตเดฑเดฟเดชเดพเดฑเตเดฑเต‡เดฃเตเด•เตพ: เดฎเตเดฏเตฝ เดฆเตเดตเดพเดฐเดคเตเดคเดฟเดจเต เดŽเดคเตเดฐ เด†เดดเดฎเตเดฃเตเดŸเต? เดจเดฎเตเด•เตเด•เต เดถเตเดฐเต‡เดฃเดฟเดฏเดฟเดฒเต‚เดŸเต† เดชเต‹เด•เดพเด‚
เด…เดญเตเดฏเตผเดคเตเดฅเดจ เดตเดณเดฐเต† เดฌเตเดฆเตเดงเดฟเดฎเตเดŸเตเดŸเตเดณเตเดณเดคเดพเดฏเดฟ เดฎเดพเดฑเตเดจเตเดจเดคเดฟเดจเดพเตฝ, เด‡เดจเดฟเดชเตเดชเดฑเดฏเตเดจเตเดจเดต เด†เดถเดฏเดคเตเดคเดฟเดจเตเดฑเต† เดคเต†เดณเดฟเดตเดพเดฏเดฟ เดฎเดพเดคเตเดฐเด‚ เดŽเดŸเตเด•เตเด•เดฃเด‚. เดŽเดจเตเดจเดพเตฝ เด‡เดคเต เดจเดฟเด™เตเด™เดณเตเดŸเต† เดกเดพเดฑเตเดฑเดพเดฌเต‡เดธเดฟเตฝ เด†เดงเดฟเดชเดคเตเดฏเด‚ เดธเตเดฅเดพเดชเดฟเด•เตเด•เตเด•เดฏเดพเดฃเต†เด™เตเด•เดฟเตฝ, เดธเดฎเดพเดจเดฎเดพเดฏ เดธเดพเด™เตเด•เต‡เดคเดฟเด• เดตเดฟเดฆเตเดฏเด•เตพ เด‰เดชเดฏเต‹เด—เดฟเด•เตเด•เตเดจเตเดจเดคเดฟเดจเต†เด•เตเด•เตเดฑเดฟเดšเตเดšเต เดจเดฟเด™เตเด™เตพ เดšเดฟเดจเตเดคเดฟเด•เตเด•เดฃเด‚.

เด•เตเดฑเดšเตเดšเต เดฒเดณเดฟเดคเดฎเดพเดฏ เดชเตเดฐเดธเตเดคเดพเดตเดจเด•เดณเดฟเตฝ เดจเดฟเดจเตเดจเต เดจเดฎเตเด•เตเด•เต เด†เดฐเด‚เดญเดฟเด•เตเด•เดพเด‚:

  • เดกเดพเดฑเตเดฑเดพเดฌเต‡เดธเดฟเตฝ เดจเดฟเดจเตเดจเตเดณเตเดณ เด…เดคเต‡ เดฑเต†เด•เตเด•เต‹เตผเดกเต เด’เดฐเดฟเด•เตเด•เตฝ เดฎเดพเดคเตเดฐเด‚ เดตเดพเดฏเดฟเด•เตเด•เตเดจเตเดจเดคเดพเดฃเต เดจเดฒเตเดฒเดคเต.
  • เดกเดพเดฑเตเดฑเดพเดฌเต‡เดธเดฟเตฝ เดจเดฟเดจเตเดจเตเดณเตเดณ เดฐเต‡เด–เด•เตพ เดฌเดพเดšเตเดšเตเด•เดณเดฟเตฝ เดตเดพเดฏเดฟเด•เตเด•เตเดจเตเดจเดคเต เด•เต‚เดŸเตเดคเตฝ เด•เดพเดฐเตเดฏเด•เตเดทเดฎเดฎเดพเดฃเตเด’เดฑเตเดฑเดฏเตเด•เตเด•เต‡เด•เตเด•เดพเตพ.

เด‡เดชเตเดชเต‹เตพ เดจเดฎเตเด•เตเด•เต เด†เดตเดถเตเดฏเดฎเตเดณเตเดณ เด…เดญเตเดฏเตผเดคเตเดฅเดจ เดจเดฟเตผเดฎเตเดฎเดฟเด•เตเด•เดพเตป เดถเตเดฐเดฎเดฟเด•เตเด•เดพเด‚.

เด˜เดŸเตเดŸเด‚ เด•เตเดธเดจเตเดฎเตเด•เตเดธ

เดตเตเดฏเด•เตเดคเดฎเดพเดฏเตเด‚, เด†เดตเตผเดคเตเดคเดจเด‚ เด†เดฐเด‚เดญเดฟเด•เตเด•เตเดฎเตเดชเต‹เตพ (เด…เดคเดฟเดฒเตเดฒเดพเดคเต† เดจเดฎเตเดฎเตพ เดŽเดตเดฟเดŸเต†เดฏเดพเดฏเดฟเดฐเดฟเด•เตเด•เตเด‚!) เดชเตเดฐเดพเดฐเด‚เดญ เดเดกเดจเตเดฑเดฟเดซเดฏเดฑเตเด•เดณเตเดŸเต† เด—เดฃเดคเตเดคเต† เด…เดŸเดฟเดธเตเดฅเดพเดจเดฎเดพเด•เตเด•เดฟ เด‡เดฒเด•เดณเตเดŸเต† เดฐเต‡เด–เด•เตพ เดคเดจเตเดจเต† เด•เตเดฑเดฏเตเด•เตเด•เต‡เดฃเตเดŸเดฟ เดตเดฐเตเด‚:

WITH RECURSIVE tree AS (
  SELECT
    rec -- ัั‚ะพ ั†ะตะปัŒะฝะฐั ะทะฐะฟะธััŒ ั‚ะฐะฑะปะธั†ั‹
  , id::text chld -- ัั‚ะพ "ะฝะฐะฑะพั€" ะฟั€ะธะฒะตะดัˆะธั… ััŽะดะฐ ะธัั…ะพะดะฝั‹ั… ะปะธัั‚ัŒะตะฒ
  FROM
    hier rec
  WHERE
    id = ANY('{1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192}'::integer[])
UNION ALL
  ...

"เดธเต†เดฑเตเดฑเต" เด’เดฐเต เดธเตเดŸเตเดฐเดฟเด‚เด—เดพเดฏเดฟเดŸเตเดŸเดฒเตเดฒ เดธเด‚เดญเดฐเดฟเดšเตเดšเดฟเดฐเดฟเด•เตเด•เตเดจเตเดจเดคเต เดŽเดจเตเดจเดคเต เด†เตผเด•เตเด•เต†เด™เตเด•เดฟเดฒเตเด‚ เดตเดฟเดšเดฟเดคเตเดฐเดฎเดพเดฏเดฟ เดคเต‹เดจเตเดจเดฟเดฏเดพเตฝ, เด‡เดคเดฟเดจเต เดฒเดณเดฟเดคเดฎเดพเดฏ เด’เดฐเต เดตเดฟเดถเดฆเต€เด•เดฐเดฃเดฎเตเดฃเตเดŸเต. เดธเตเดŸเตเดฐเดฟเด‚เด—เตเด•เตพเด•เตเด•เดพเดฏเดฟ เด’เดฐเต เดฌเดฟเตฝเดฑเตเดฑเต-เด‡เตป เด…เด—เตเดฐเด—เต‡เดฑเตเดฑเดฟเด‚เด—เต "เด—เตเดฒเต‚เดฏเดฟเด‚เด—เต" เดซเด‚เด—เตเดทเตป เด‰เดฃเตเดŸเต string_agg, เดŽเดจเตเดจเดพเตฝ เด…เดฑเต‡เด•เตพเด•เตเด•เดฒเตเดฒ. เด…เดตเตพ เด†เดฃเต†เด™เตเด•เดฟเดฒเตเด‚ เดธเตเดตเดจเตเดคเดฎเดพเดฏเดฟ เดจเดŸเดชเตเดชเดฟเดฒเดพเด•เตเด•เดพเตป เดŽเดณเตเดชเตเดชเดฎเดพเดฃเต.

เด˜เดŸเตเดŸเด‚ เด•เตเดธเดจเตเดฎเตเด•เตเดธ

เด‡เดชเตเดชเต‹เตพ เดจเดฎเตเด•เตเด•เต เด’เดฐเต เด•เต‚เดŸเตเดŸเด‚ เดธเต†เด•เตเดทเตป เดเดกเดฟเด•เตพ เดฒเดญเดฟเด•เตเด•เตเด‚, เด…เดคเต เด•เต‚เดŸเตเดคเตฝ เดตเดพเดฏเดฟเด•เตเด•เต‡เดฃเตเดŸเดคเตเดฃเตเดŸเต. เดฎเดฟเด•เตเด•เดตเดพเดฑเตเด‚ เดŽเดฒเตเดฒเดพเดฏเตโ€Œเดชเตเดชเต‹เดดเตเด‚ เด…เดต เดฏเดฅเดพเตผเดคเตเดฅ เดธเต†เดฑเตเดฑเดฟเดจเตเดฑเต† เดตเตเดฏเดคเตเดฏเดธเตโ€Œเดค เดฑเต†เด•เตเด•เต‹เตผเดกเตเด•เดณเดฟเตฝ เดคเดจเดฟเดชเตเดชเด•เตผเดชเตเดชเดพเด•เตเด•เตเด‚ - เด…เดคเดฟเดจเดพเตฝ เดžเด™เตเด™เตพ เดšเต†เดฏเตเดฏเตเด‚ เด…เดตเดฐเต† เด—เตเดฐเต‚เดชเตเดชเตเดšเต†เดฏเตเดฏเตเด•, เด‰เดฑเดตเดฟเดŸ เด‡เดฒเด•เดณเต†เด•เตเด•เตเดฑเดฟเดšเตเดšเตเดณเตเดณ เดตเดฟเดตเดฐเด™เตเด™เตพ เดธเด‚เดฐเด•เตเดทเดฟเด•เตเด•เตเดฎเตเดชเต‹เตพ.

เดŽเดจเตเดจเดพเตฝ เด‡เดตเดฟเดŸเต† เดฎเต‚เดจเตเดจเต เด•เตเดดเดชเตเดชเด™เตเด™เตพ เดจเดฎเตเดฎเต† เด•เดพเดคเตเดคเดฟเดฐเดฟเด•เตเด•เตเดจเตเดจเต:

  1. เด…เดจเตเดตเต‡เดทเดฃเดคเตเดคเดฟเดจเตเดฑเต† "เดธเดฌเตเดฐเต†เด•เตเด•เตผเดธเต€เดตเต" เดญเดพเด—เดคเตเดคเต เดฎเตŠเดคเตเดคเดคเตเดคเดฟเดฒเตเดณเตเดณ เดซเด‚เด—เตโ€Œเดทเดจเตเด•เตพ เด‰เตพเด•เตเด•เตŠเดณเตเดณเดพเตป เด•เดดเดฟเดฏเดฟเดฒเตเดฒ GROUP BY.
  2. เด’เดฐเต เด†เดตเตผเดคเตเดคเดจ "เดชเดŸเตเดŸเดฟเด•" เดฏเต†เด•เตเด•เตเดฑเดฟเดšเตเดšเตเดณเตเดณ เด’เดฐเต เดฑเดซเดฑเตปเดธเต เด’เดฐเต เดจเต†เดธเตเดฑเตเดฑเดกเต เดธเดฌเตเด•เตเดตเดฑเดฟเดฏเดฟเตฝ เด‰เดฃเตเดŸเดพเด•เดฐเตเดคเต.
  3. เด†เดตเตผเดคเตเดคเดจ เดญเดพเด—เดคเตเดคเดฟเดฒเต† เด’เดฐเต เด…เดญเตเดฏเตผเดคเตเดฅเดจเดฏเดฟเตฝ เด’เดฐเต CTE เด…เดŸเด™เตเด™เดฟเดฏเดฟเดฐเดฟเด•เตเด•เดฐเตเดคเต.

เดญเดพเด—เตเดฏเดตเดถเดพเตฝ, เดˆ เดชเตเดฐเดถเตเดจเด™เตเด™เดณเต†เดฒเตเดฒเดพเด‚ เดชเดฐเดฟเดนเดฐเดฟเด•เตเด•เดพเตป เดตเดณเดฐเต† เดŽเดณเตเดชเตเดชเดฎเดพเดฃเต. เด…เดตเดธเดพเดจเด‚ เดฎเตเดคเตฝ เดคเตเดŸเด™เตเด™เดพเด‚.

เด†เดตเตผเดคเตเดคเดจ เดญเดพเด—เดคเตเดคเต เดธเดฟ.เดŸเดฟ.เด‡

เด‡เดคเตเดชเต‡เดพเดฒเต† เด…เดฒเตเดฒ เดชเตเดฐเดตเตผเดคเตเดคเดฟเด•เตเด•เตเดจเตเดจเต:

WITH RECURSIVE tree AS (
  ...
UNION ALL
  WITH T (...)
  SELECT ...
)

เด…เดคเดฟเดจเดพเตฝ เด‡เดคเต เดชเตเดฐเดตเตผเดคเตเดคเดฟเด•เตเด•เตเดจเตเดจเต, เดชเดฐเดพเตปเดคเต€เดธเดฟเดธเตเด•เตพ เดตเตเดฏเดคเตเดฏเดพเดธเด‚ เดตเดฐเตเดคเตเดคเตเดจเตเดจเต!

WITH RECURSIVE tree AS (
  ...
UNION ALL
  (
    WITH T (...)
    SELECT ...
  )
)

เด’เดฐเต เด†เดตเตผเดคเตเดคเดจ "เดŸเต‡เดฌเดฟเดณเดฟเดจเต" เดŽเดคเดฟเดฐเต†เดฏเตเดณเตเดณ เดจเต†เดธเตเดฑเตเดฑเดกเต เด…เดจเตเดตเต‡เดทเดฃเด‚

เดนเตเด‚... เด’เดฐเต เดธเดฌเตเด•เตเดตเดฑเดฟเดฏเดฟเตฝ เด’เดฐเต เด†เดตเตผเดคเตเดคเดจ CTE เด†เด•เตเดธเดธเต เดšเต†เดฏเตเดฏเดพเตป เด•เดดเดฟเดฏเดฟเดฒเตเดฒ. เดชเด•เตเดทเต‡ เด…เดคเต CTE เด‰เดณเตเดณเดฟเดฒเดพเดฏเดฟเดฐเดฟเด•เตเด•เดพเด‚! เด’เดฐเต เดจเต†เดธเตเดฑเตเดฑเดกเต เด…เดญเตเดฏเตผเดคเตเดฅเดจเดฏเตเด•เตเด•เต เด‡เดคเดฟเดจเด•เด‚ เดคเดจเตเดจเต† เดˆ CTE เด†เด•เตโ€Œเดธเดธเต เดšเต†เดฏเตเดฏเดพเตป เด•เดดเดฟเดฏเตเด‚!

เด†เดตเตผเดคเตเดคเดจเดคเตเดคเดฟเดจเตเดณเตเดณเดฟเดฒเต† เด—เตเดฐเต‚เดชเตเดชเต

เด‡เดคเต เด…เดฐเต‹เดšเด•เดฎเดพเดฃเต, เดชเด•เตเดทเต‡... GROUP เด‰เดชเดฏเต‹เด—เดฟเดšเตเดšเต เด…เดจเตเด•เดฐเดฟเด•เตเด•เดพเตป เดžเด™เตเด™เตพเด•เตเด•เต เด’เดฐเต เดฒเดณเดฟเดคเดฎเดพเดฏ เดฎเดพเตผเด—เดฎเตเดฃเตเดŸเต DISTINCT ON เดตเดฟเตปเดกเต‹ เดซเด‚เด—เตโ€Œเดทเดจเตเด•เดณเตเด‚!

SELECT
  (rec).pid id
, string_agg(chld::text, ',') chld
FROM
  tree
WHERE
  (rec).pid IS NOT NULL
GROUP BY 1 -- ะฝะต ั€ะฐะฑะพั‚ะฐะตั‚!

เด‡เดคเต เด‡เด™เตเด™เดจเต†เดฏเดพเดฃเต เดชเตเดฐเดตเตผเดคเตเดคเดฟเด•เตเด•เตเดจเตเดจเดคเต!

SELECT DISTINCT ON((rec).pid)
  (rec).pid id
, string_agg(chld::text, ',') OVER(PARTITION BY (rec).pid) chld
FROM
  tree
WHERE
  (rec).pid IS NOT NULL

เดธเด‚เด–เตเดฏเดพ เดเดกเดฟ เดŽเดจเตเดคเดฟเดจเดพเดฃเต เดŸเต†เด•เตโ€Œเดธเตโ€Œเดฑเตเดฑเดพเด•เตเด•เดฟ เดฎเดพเดฑเตเดฑเดฟเดฏเดคเต†เดจเตเดจเต เด‡เดชเตเดชเต‹เตพ เดจเดฎเตเดฎเตพ เด•เดพเดฃเตเดจเตเดจเต - เด…เด™เตเด™เดจเต† เด…เดตเดฏเต† เด•เต‹เดฎเด•เดณเดพเตฝ เดตเต‡เตผเดคเดฟเดฐเดฟเด•เตเด•เดพเดจเดพเด•เตเด‚!

เด˜เดŸเตเดŸเด‚ เด•เตเดธเดจเตเดฎเตเด•เตเดธ

เดซเตˆเดจเดฒเดฟเดจเดพเดฏเดฟ เดžเด™เตเด™เตพเด•เตเด•เต เด’เดจเตเดจเตเด‚ เด…เดตเดถเต‡เดทเดฟเด•เตเด•เตเดจเตเดจเดฟเดฒเตเดฒ:

  • เด—เตเดฐเต‚เดชเตเดชเตเดšเต†เดฏเตเดค เดเดกเดฟเด•เดณเตเดŸเต† เด’เดฐเต เด•เต‚เดŸเตเดŸเดคเตเดคเต† เด…เดŸเดฟเดธเตเดฅเดพเดจเดฎเดพเด•เตเด•เดฟเดฏเดพเดฃเต เดžเด™เตเด™เตพ "เดตเดฟเดญเดพเด—เด‚" เดฑเต†เด•เตเด•เต‹เตผเดกเตเด•เตพ เดตเดพเดฏเดฟเด•เตเด•เตเดจเตเดจเดคเต
  • เดžเด™เตเด™เตพ เด•เตเดฑเดฏเตเด•เตเด•เตเดจเตเดจ เดตเดฟเดญเดพเด—เด™เตเด™เดณเต† เดฏเดฅเดพเตผเดคเตเดฅ เดทเต€เดฑเตเดฑเตเด•เดณเตเดŸเต† "เดธเต†เดฑเตเดฑเตเด•เดณเตเดฎเดพเดฏเดฟ" เดคเดพเดฐเดคเดฎเตเดฏเด‚ เดšเต†เดฏเตเดฏเตเดจเตเดจเต
  • เด‰เดชเดฏเต‹เด—เดฟเดšเตเดšเต เดธเต†เดฑเตเดฑเต-เดธเตเดŸเตเดฐเดฟเด‚เด—เต "เดตเดฟเด•เดธเดฟเดชเตเดชเดฟเด•เตเด•เตเด•" unnest(string_to_array(chld, ',')::integer[])

WITH RECURSIVE tree AS (
  SELECT
    rec
  , id::text chld
  FROM
    hier rec
  WHERE
    id = ANY('{1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192}'::integer[])
UNION ALL
  (
    WITH prnt AS (
      SELECT DISTINCT ON((rec).pid)
        (rec).pid id
      , string_agg(chld::text, ',') OVER(PARTITION BY (rec).pid) chld
      FROM
        tree
      WHERE
        (rec).pid IS NOT NULL
    )
    , nodes AS (
      SELECT
        rec
      FROM
        hier rec
      WHERE
        id = ANY(ARRAY(
          SELECT
            id
          FROM
            prnt
        ))
    )
    SELECT
      nodes.rec
    , prnt.chld
    FROM
      prnt
    JOIN
      nodes
        ON (nodes.rec).id = prnt.id
  )
)
SELECT
  unnest(string_to_array(chld, ',')::integer[]) leaf
, (rec).*
FROM
  tree;

PostgreSQL เด†เดจเตเดฑเดฟเดชเดพเดฑเตเดฑเต‡เดฃเตเด•เตพ: เดฎเตเดฏเตฝ เดฆเตเดตเดพเดฐเดคเตเดคเดฟเดจเต เดŽเดคเตเดฐ เด†เดดเดฎเตเดฃเตเดŸเต? เดจเดฎเตเด•เตเด•เต เดถเตเดฐเต‡เดฃเดฟเดฏเดฟเดฒเต‚เดŸเต† เดชเต‹เด•เดพเด‚
[explain.tensor.ru-เตฝ เด•เดพเดฃเตเด•]

เด…เดตเดฒเด‚เดฌเด‚: www.habr.com

เด’เดฐเต เด…เดญเดฟเดชเตเดฐเดพเดฏเด‚ เดšเต‡เตผเด•เตเด•เตเด•