ΠΠΎ ΡΠ»ΠΎΠΆΠ΅Π½ΠΈ ERP ΡΠΈΡΡΠ΅ΠΌΠΈ ΠΌΠ½ΠΎΠ³Ρ Π΅Π½ΡΠΈΡΠ΅ΡΠΈ ΠΈΠΌΠ°Π°Ρ Ρ ΠΈΠ΅ΡΠ°ΡΡ ΠΈΡΠΊΠ° ΠΏΡΠΈΡΠΎΠ΄Π°ΠΊΠΎΠ³Π° ΡΠ΅ ΡΠ΅Π΄Π°Ρ Ρ ΠΎΠΌΠΎΠ³Π΅Π½ΠΈ ΠΏΡΠ΅Π΄ΠΌΠ΅ΡΠΈ Π΄ΡΠ²ΠΎ Π½Π° ΠΎΠ΄Π½ΠΎΡΠΈΡΠ΅ ΠΏΡΠ΅Π΄ΠΎΠΊ-ΠΏΠΎΡΠΎΠΌΠΎΠΊ - ΠΎΠ²Π° Π΅ ΠΎΡΠ³Π°Π½ΠΈΠ·Π°ΡΠΈΡΠΊΠ°ΡΠ° ΡΡΡΡΠΊΡΡΡΠ° Π½Π° ΠΏΡΠ΅ΡΠΏΡΠΈΡΠ°ΡΠΈΠ΅ΡΠΎ (ΡΠΈΡΠ΅ ΠΎΠ²ΠΈΠ΅ Π³ΡΠ°Π½ΠΊΠΈ, ΠΎΠ΄Π΄Π΅Π»Π΅Π½ΠΈΡΠ° ΠΈ ΡΠ°Π±ΠΎΡΠ½ΠΈ Π³ΡΡΠΏΠΈ), ΠΈ ΠΊΠ°ΡΠ°Π»ΠΎΠ³ΠΎΡ Π½Π° ΡΡΠΎΠΊΠΈ, ΠΈ ΠΎΠ±Π»Π°ΡΡΠΈΡΠ΅ Π½Π° ΡΠ°Π±ΠΎΡΠ°, ΠΈ Π³Π΅ΠΎΠ³ΡΠ°ΡΠΈΡΠ°ΡΠ° Π½Π° ΠΏΡΠΎΠ΄Π°ΠΆΠ½ΠΈΡΠ΅ ΠΌΠ΅ΡΡΠ°,...
ΠΡΡΡΠ½ΠΎΡΡ, Π½Π΅ ΠΏΠΎΡΡΠΎΠΈ
ΠΠΎΡΡΠΎΡΠ°Ρ ΠΌΠ½ΠΎΠ³Ρ Π½Π°ΡΠΈΠ½ΠΈ Π·Π° ΡΠΊΠ»Π°Π΄ΠΈΡΠ°ΡΠ΅ Π½Π° ΡΠ°ΠΊΠ²ΠΎ Π΄ΡΠ²ΠΎ Π²ΠΎ DBMS, Π½ΠΎ Π΄Π΅Π½Π΅Ρ ΡΠ΅ ΡΠ΅ ΡΠΎΠΊΡΡΠΈΡΠ°ΠΌΠ΅ Π½Π° ΡΠ°ΠΌΠΎ Π΅Π΄Π½Π° ΠΎΠΏΡΠΈΡΠ°:
CREATE TABLE hier(
id
integer
PRIMARY KEY
, pid
integer
REFERENCES hier
, data
json
);
CREATE INDEX ON hier(pid); -- Π½Π΅ Π·Π°Π±ΡΠ²Π°Π΅ΠΌ, ΡΡΠΎ FK Π½Π΅ ΠΏΠΎΠ΄ΡΠ°Π·ΡΠΌΠ΅Π²Π°Π΅Ρ Π°Π²ΡΠΎΡΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΈΠ½Π΄Π΅ΠΊΡΠ°, Π² ΠΎΡΠ»ΠΈΡΠΈΠ΅ ΠΎΡ PK
Π Π΄ΠΎΠ΄Π΅ΠΊΠ° ΡΠΈΡΠΊΠ°ΡΠ΅ Π²ΠΎ Π΄Π»Π°Π±ΠΎΡΠΈΠ½ΠΈΡΠ΅ Π½Π° Ρ ΠΈΠ΅ΡΠ°ΡΡ ΠΈΡΠ°ΡΠ°, ΡΡΠΏΠ΅Π»ΠΈΠ²ΠΎ ΡΠ΅ΠΊΠ° Π΄Π° Π²ΠΈΠ΄ΠΈΡΠ΅ ΠΊΠΎΠ»ΠΊΡ Π²Π°ΡΠΈΡΠ΅ βΠ½Π°ΠΈΠ²Π½ΠΈβ Π½Π°ΡΠΈΠ½ΠΈ Π½Π° ΡΠ°Π±ΠΎΡΠ° ΡΠΎ ΡΠ°ΠΊΠ²Π° ΡΡΡΡΠΊΡΡΡΠ° ΡΠ΅ Π±ΠΈΠ΄Π°Ρ [Π½Π΅]Π΅ΡΠ΅ΠΊΡΠΈΠ²Π½ΠΈ.
ΠΠ° Π³ΠΈ ΠΏΠΎΠ³Π»Π΅Π΄Π½Π΅ΠΌΠ΅ ΡΠΈΠΏΠΈΡΠ½ΠΈΡΠ΅ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠΈ ΡΡΠΎ ΡΠ΅ ΠΏΠΎΡΠ°Π²ΡΠ²Π°Π°Ρ, Π½ΠΈΠ²Π½Π°ΡΠ° ΠΈΠΌΠΏΠ»Π΅ΠΌΠ΅Π½ΡΠ°ΡΠΈΡΠ° Π²ΠΎ SQL ΠΈ Π΄Π° ΡΠ΅ ΠΎΠ±ΠΈΠ΄Π΅ΠΌΠ΅ Π΄Π° Π³ΠΈ ΠΏΠΎΠ΄ΠΎΠ±ΡΠΈΠΌΠ΅ Π½ΠΈΠ²Π½ΠΈΡΠ΅ ΠΏΠ΅ΡΡΠΎΡΠΌΠ°Π½ΡΠΈ.
#1. ΠΠΎΠ»ΠΊΡ Π΄Π»Π°Π±ΠΎΠΊΠ° Π΅ Π·Π°ΡΠ°ΡΠΊΠ°ΡΠ° Π΄ΡΠΏΠΊΠ°?
ΠΡΠ΄Π΅, ΡΠΎ ΡΠΈΠ³ΡΡΠ½ΠΎΡΡ, Π΄Π° ΠΏΡΠΈΡΠ°ΡΠΈΠΌΠ΅ Π΄Π΅ΠΊΠ° ΠΎΠ²Π°Π° ΡΡΡΡΠΊΡΡΡΠ° ΡΠ΅ ΡΠ° ΠΎΠ΄ΡΠ°Π·ΡΠ²Π° ΠΏΠΎΠ΄ΡΠ΅Π΄Π΅Π½ΠΎΡΡΠ° Π½Π° ΠΎΠ΄Π΄Π΅Π»Π΅Π½ΠΈΡΠ°ΡΠ° Π²ΠΎ ΡΡΡΡΠΊΡΡΡΠ°ΡΠ° Π½Π° ΠΎΡΠ³Π°Π½ΠΈΠ·Π°ΡΠΈΡΠ°ΡΠ°: ΠΎΠ΄Π΄Π΅Π»Π΅Π½ΠΈΡΠ°, ΠΎΠ΄Π΄Π΅Π»Π΅Π½ΠΈΡΠ°, ΡΠ΅ΠΊΡΠΎΡΠΈ, Π³ΡΠ°Π½ΠΊΠΈ, ΡΠ°Π±ΠΎΡΠ½ΠΈ Π³ΡΡΠΏΠΈ... - ΠΊΠ°ΠΊΠΎ ΠΈ Π΄Π° Π³ΠΈ Π½Π°ΡΠ΅ΠΊΡΠ²Π°ΡΠ΅.
ΠΡΠ²ΠΎ, Π΄Π° Π³ΠΎ Π³Π΅Π½Π΅ΡΠΈΡΠ°ΠΌΠ΅ Π½Π°ΡΠ΅ΡΠΎ βΠ΄ΡΠ²ΠΎβ ΠΎΠ΄ 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
ΠΠ° ΠΎΠ²ΠΈΠ΅ ΠΏΡΠ°ΡΠ°ΡΠ° Π³ΠΎ ΠΊΠΎΡΠΈΡΡΠ΅Π²ΠΌΠ΅ ΡΠΈΠΏΠΈΡΠ½ΠΎΡΠΎ ΡΠ΅ΠΊΡΡΠ·ΠΈΠ²Π΅Π½ JOIN:
ΠΡΠΈΠ³Π»Π΅Π΄Π½ΠΎ, ΡΠΎ ΠΎΠ²ΠΎΡ ΠΌΠΎΠ΄Π΅Π» Π½Π° Π±Π°ΡΠ°ΡΠ΅ Π±ΡΠΎΡΠΎΡ Π½Π° ΠΏΠΎΠ²ΡΠΎΡΡΠ²Π°ΡΠ° ΡΠ΅ ΠΎΠ΄Π³ΠΎΠ²Π°ΡΠ° Π½Π° Π²ΠΊΡΠΏΠ½ΠΈΠΎΡ Π±ΡΠΎΡ Π½Π° ΠΏΠΎΡΠΎΠΌΡΠΈ (ΠΈ ΠΈΠΌΠ° Π½Π΅ΠΊΠΎΠ»ΠΊΡ Π΄Π΅ΡΠ΅ΡΠΈΡΠΈ ΠΎΠ΄ Π½ΠΈΠ²), ΠΈ ΠΎΠ²Π° ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΏΠΎΡΡΠ°Π΅ Π΄ΠΎΡΡΠ° Π·Π½Π°ΡΠΈΡΠ΅Π»Π½ΠΈ ΡΠ΅ΡΡΡΡΠΈ ΠΈ, ΠΊΠ°ΠΊΠΎ ΡΠ΅Π·ΡΠ»ΡΠ°Ρ Π½Π° ΡΠΎΠ°, Π²ΡΠ΅ΠΌΠ΅.
ΠΡΠ΄Π΅ Π΄Π° Π³ΠΎ ΠΏΡΠΎΠ²Π΅ΡΠΈΠΌΠ΅ βΠ½Π°ΡΡΠΈΡΠΎΠΊΠΎΡΠΎβ ΠΏΠΎΠ΄Π΄ΡΠ²ΠΎ:
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;
ΠΡΠ΅ΠΊΡΠ²Π°Π½ΠΎ Π³ΠΈ Π½Π°ΡΠ΄ΠΎΠ²ΠΌΠ΅ ΡΠΈΡΠ΅ 30 Π·Π°ΠΏΠΈΡΠΈ. ΠΠΎ, ΡΠΈΠ΅ ΠΏΠΎΡΡΠΎΡΠΈΡΠ° 60% ΠΎΠ΄ Π²ΠΊΡΠΏΠ½ΠΎΡΠΎ Π²ΡΠ΅ΠΌΠ΅ Π½Π° ΠΎΠ²Π° - Π·Π°ΡΠΎΠ° ΡΡΠΎ Π½Π°ΠΏΡΠ°Π²ΠΈΡΠ° ΠΈ 30 ΠΏΡΠ΅Π±Π°ΡΡΠ²Π°ΡΠ° Π²ΠΎ ΠΈΠ½Π΄Π΅ΠΊΡΠΎΡ. ΠΠ°Π»ΠΈ Π΅ ΠΌΠΎΠΆΠ½ΠΎ Π΄Π° ΡΠ΅ Π½Π°ΠΏΡΠ°Π²ΠΈ ΠΏΠΎΠΌΠ°Π»ΠΊΡ?
ΠΠ°ΡΠΎΠ²Π½ΠΎ Π»Π΅ΠΊΡΠΎΡΠΈΡΠ°ΡΠ΅ ΠΏΠΎ ΠΈΠ½Π΄Π΅ΠΊΡ
ΠΠ°Π»ΠΈ ΡΡΠ΅Π±Π° Π΄Π° Π½Π°ΠΏΡΠ°Π²ΠΈΠΌΠ΅ ΠΏΠΎΡΠ΅Π±Π½ΠΎ ΠΈΠ½Π΄Π΅ΠΊΡΠ½ΠΎ Π±Π°ΡΠ°ΡΠ΅ Π·Π° ΡΠ΅ΠΊΠΎΡ ΡΠ°Π·ΠΎΠ»? ΠΠ·Π»Π΅Π³ΡΠ²Π° Π΄Π΅ΠΊΠ° Π½Π΅ - ΠΌΠΎΠΆΠ΅ΠΌΠ΅ Π΄Π° ΠΏΡΠΎΡΠΈΡΠ°ΠΌΠ΅ ΠΎΠ΄ ΠΈΠ½Π΄Π΅ΠΊΡΠΎΡ ΠΊΠΎΡΠΈΡΡΠ΅ΡΡΠΈ Π½Π΅ΠΊΠΎΠ»ΠΊΡ ΠΊΠΎΠΏΡΠΈΡΠ° ΠΎΠ΄Π΅Π΄Π½Π°Ρ Π²ΠΎ Π΅Π΄Π΅Π½ ΠΏΠΎΠ²ΠΈΠΊ ΡΠΎ ΠΏΠΎΠΌΠΎΡ Π½Π° = ANY(array)
.
Π Π²ΠΎ ΡΠ΅ΠΊΠΎΡΠ° ΡΠ°ΠΊΠ²Π° Π³ΡΡΠΏΠ° Π½Π° ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΠΈ ΠΌΠΎΠΆΠ΅ΠΌΠ΅ Π΄Π° Π³ΠΈ Π·Π΅ΠΌΠ΅ΠΌΠ΅ ΡΠΈΡΠ΅ ID-ΠΈ ΠΏΡΠΎΠ½Π°ΡΠ΄Π΅Π½ΠΈ Π²ΠΎ ΠΏΡΠ΅ΡΡ ΠΎΠ΄Π½ΠΈΠΎΡ ΡΠ΅ΠΊΠΎΡ ΠΏΠΎ βΡΠ°Π·Π»ΠΈβ. Π’ΠΎΠ° Π΅, Π½Π° ΡΠ΅ΠΊΠΎΡ ΡΠ»Π΅Π΄Π΅Π½ ΡΠ΅ΠΊΠΎΡ Π½ΠΈΠ΅ ΡΠ΅ ΠΏΠΎΠ±Π°ΡΠ°ΡΡΠ΅ Π³ΠΈ ΡΠΈΡΠ΅ ΠΏΠΎΡΠΎΠΌΡΠΈ Π½Π° ΠΎΠ΄ΡΠ΅Π΄Π΅Π½ΠΎ Π½ΠΈΠ²ΠΎ ΠΎΠ΄Π΅Π΄Π½Π°Ρ.
Π‘Π°ΠΌΠΎ, ΡΡΠΊΠ° Π΅ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠΎΡ, Π²ΠΎ ΡΠ΅ΠΊΡΡΠ·ΠΈΠ²Π΅Π½ ΠΈΠ·Π±ΠΎΡ, Π½Π΅ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΡΠΈ ΠΏΡΠΈΡΡΠ°ΠΏΠΈΡΠ΅ Π²ΠΎ Π²Π³Π½Π΅Π·Π΄Π΅Π½ΠΎ Π±Π°ΡΠ°ΡΠ΅, Π½ΠΎ ΡΡΠ΅Π±Π° Π½Π΅ΠΊΠ°ΠΊΠΎ Π΄Π° Π³ΠΎ ΠΈΠ·Π±Π΅ΡΠ΅ΠΌΠ΅ ΡΠ°ΠΌΠΎ ΠΎΠ½Π° ΡΡΠΎ Π΅ ΠΏΡΠΎΠ½Π°ΡΠ΄Π΅Π½ΠΎ Π½Π° ΠΏΡΠ΅ΡΡ
ΠΎΠ΄Π½ΠΎΡΠΎ Π½ΠΈΠ²ΠΎ... ΠΠ·Π»Π΅Π³ΡΠ²Π° Π΄Π΅ΠΊΠ° Π΅ Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ Π΄Π° ΡΠ΅ Π½Π°ΠΏΡΠ°Π²ΠΈ Π²Π³Π½Π΅Π·Π΄Π΅Π½ΠΎ Π±Π°ΡΠ°ΡΠ΅ Π·Π° ΡΠ΅Π»ΠΈΠΎΡ ΠΈΠ·Π±ΠΎΡ, Π½ΠΎ Π·Π° Π½Π΅Π³ΠΎΠ²ΠΎΡΠΎ ΡΠΏΠ΅ΡΠΈΡΠΈΡΠ½ΠΎ ΠΏΠΎΠ»Π΅ Π΅ ΠΌΠΎΠΆΠ½ΠΎ. Π ΠΎΠ²Π° ΠΏΠΎΠ»Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° Π±ΠΈΠ΄Π΅ ΠΈ Π½ΠΈΠ·Π° - ΡΡΠΎ Π΅ ΠΎΠ½Π° ΡΡΠΎ ΡΡΠ΅Π±Π° Π΄Π° Π³ΠΎ ΠΊΠΎΡΠΈΡΡΠΈΠΌΠ΅ ANY
.
ΠΠ²ΡΡΠΈ ΠΌΠ°Π»ΠΊΡ Π»ΡΠ΄ΠΎ, Π½ΠΎ Π½Π° Π΄ΠΈΡΠ°Π³ΡΠ°ΠΌΠΎΡ ΡΓ¨ Π΅ Π΅Π΄Π½ΠΎΡΡΠ°Π²Π½ΠΎ.
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;
Π ΡΡΠΊΠ° Π½Π°ΡΠ²Π°ΠΆΠ½ΠΎΡΠΎ Π½Π΅ Π΅ ΡΠ°ΠΌΠ½ΠΎΠΌΠ΅ΡΠ½ΠΎ ΠΏΠΎΠ±Π΅Π΄ΠΈ 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
, ΡΡΠΎ ΡΠ΅ Π½ΠΈ ΠΎΠ²ΠΎΠ·ΠΌΠΎΠΆΠΈ Π²Π΅Π΄Π½Π°Ρ Π΄Π° ΠΏΡΠΈΡΡΠ°ΠΏΠΈΠΌΠ΅ Π΄ΠΎ ΠΏΠΎΠ»ΠΈΡΠ°ΡΠ° Π½Π° ΡΠ΅ΠΊΡΡΠ·ΠΈΠ²Π½Π°ΡΠ° βΡΠ°Π±Π΅Π»Π°β ΠΈ Π΄Π° ΠΊΠΎΡΠΈΡΡΠΈΠΌΠ΅ Π·Π±ΠΈΡΠ½Π° ΡΡΠ½ΠΊΡΠΈΡΠ° ΡΠΎ ΡΡΠ»ΠΎΠ² Π·Π° ΡΠΈΠ»ΡΡΠΈΡΠ°ΡΠ΅ Π²ΡΠ· ΠΎΡΠ½ΠΎΠ²Π° Π½Π° ΡΠ°Π·ΠΎΠ» Π·Π° Π΄Π° Π³ΠΎ Π½Π°ΠΌΠ°Π»ΠΈΠΌΠ΅ ΠΌΠ½ΠΎΠΆΠ΅ΡΡΠ²ΠΎΡΠΎ ΠΊΠ»ΡΡΠ΅Π²ΠΈ:
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;
Π£ΡΠΏΠ΅Π°Π²ΠΌΠ΅ Π΄Π° Π½Π°ΠΌΠ°Π»ΠΈΠΌΠ΅ ΡΡΡΠ΅ Π΅Π΄Π΅Π½ ΠΈΠ½Π΄Π΅ΠΊΡΠ΅Π½ ΠΏΠΎΠ²ΠΈΠΊ ΠΈ ΠΎΡΠ²ΠΎΠΈ ΠΏΠΎΠ²Π΅ΡΠ΅ ΠΎΠ΄ 2 ΠΏΠ°ΡΠΈ Π²ΠΎ ΠΎΠ±Π΅ΠΌ Π»Π΅ΠΊΡΠΎΡΠΈΡΠ°Π½ΠΈ.
#2. ΠΠ° ΡΠ΅ ββΠ²ΡΠ°ΡΠΈΠΌΠ΅ Π½Π° ΠΊΠΎΡΠ΅Π½ΠΈΡΠ΅
ΠΠ²ΠΎΡ Π°Π»Π³ΠΎΡΠΈΡΠ°ΠΌ ΡΠ΅ Π±ΠΈΠ΄Π΅ ΠΊΠΎΡΠΈΡΠ΅Π½ Π°ΠΊΠΎ ΡΡΠ΅Π±Π° Π΄Π° ΡΠΎΠ±Π΅ΡΠ΅ΡΠ΅ Π·Π°ΠΏΠΈΡΠΈ Π·Π° ΡΠΈΡΠ΅ Π΅Π»Π΅ΠΌΠ΅Π½ΡΠΈ βΠ³ΠΎΡΠ΅ Π½Π° Π΄ΡΠ²ΠΎΡΠΎβ, ΠΏΡΠΈΡΠΎΠ° Π·Π°Π΄ΡΠΆΡΠ²Π°ΡΡΠΈ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΠΈ Π·Π° ΡΠΎΠ° ΠΊΠΎΡ ΠΈΠ·Π²ΠΎΡΠ΅Π½ Π»ΠΈΡΡ (ΠΈ ΡΠΎ ΠΊΠΎΠΈ ΠΈΠ½Π΄ΠΈΠΊΠ°ΡΠΎΡΠΈ) Π³ΠΎ ΠΏΡΠ΅Π΄ΠΈΠ·Π²ΠΈΠΊΠ°Π» ΡΠΎΡ Π΄Π° Π±ΠΈΠ΄Π΅ Π²ΠΊΠ»ΡΡΠ΅Π½ Π²ΠΎ ΠΏΡΠΈΠΌΠ΅ΡΠΎΠΊΠΎΡ - Π½Π° ΠΏΡΠΈΠΌΠ΅Ρ, Π΄Π° Π³Π΅Π½Π΅ΡΠΈΡΠ° Π·Π±ΠΈΡΠ΅Π½ ΠΈΠ·Π²Π΅ΡΡΠ°Ρ ΡΠΎ Π°Π³ΡΠ΅Π³Π°ΡΠΈΡΠ° Π²ΠΎ ΡΠ°Π·Π»ΠΈ.
ΠΠ½Π° ΡΡΠΎ ΡΠ»Π΅Π΄ΠΈ ΡΡΠ΅Π±Π° Π΄Π° ΡΠ΅ Π·Π΅ΠΌΠ΅ ΡΠ°ΠΌΠΎ ΠΊΠ°ΠΊΠΎ Π΄ΠΎΠΊΠ°Π· Π·Π° ΠΊΠΎΠ½ΡΠ΅ΠΏΡ, Π±ΠΈΠ΄Π΅ΡΡΠΈ Π±Π°ΡΠ°ΡΠ΅ΡΠΎ ΡΠ΅ ΠΏΠΎΠΊΠ°ΠΆΡΠ²Π° ΠΊΠ°ΠΊΠΎ ΠΌΠ½ΠΎΠ³Ρ Π½Π΅Π·Π³ΠΎΠ΄Π½ΠΎ. ΠΠΎ, Π°ΠΊΠΎ Π΄ΠΎΠΌΠΈΠ½ΠΈΡΠ° Π²ΠΎ Π²Π°ΡΠ°ΡΠ° Π±Π°Π·Π° Π½Π° ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ, ΡΡΠ΅Π±Π° Π΄Π° ΡΠ°Π·ΠΌΠΈΡΠ»ΠΈΡΠ΅ Π·Π° ΠΊΠΎΡΠΈΡΡΠ΅ΡΠ΅ ΡΠ»ΠΈΡΠ½ΠΈ ΡΠ΅Ρ
Π½ΠΈΠΊΠΈ.
ΠΠ° ΠΏΠΎΡΠ½Π΅ΠΌΠ΅ ΡΠΎ Π½Π΅ΠΊΠΎΠ»ΠΊΡ Π΅Π΄Π½ΠΎΡΡΠ°Π²Π½ΠΈ ΠΈΠ·ΡΠ°Π²ΠΈ:
- ΠΡΡΠΈΠΎΡ Π·Π°ΠΏΠΈΡ ΠΎΠ΄ Π±Π°Π·Π°ΡΠ° Π½Π° ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ ΠΠ°ΡΠ΄ΠΎΠ±ΡΠΎ Π΅ Π΄Π° Π³ΠΎ ΠΏΡΠΎΡΠΈΡΠ°ΡΠ΅ ΡΠ°ΠΌΠΎ Π΅Π΄Π½Π°Ρ.
- ΠΠ°ΠΏΠΈΡΠΈ ΠΎΠ΄ Π±Π°Π·Π°ΡΠ° Π½Π° ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ ΠΠΎΠ΅ΡΠΈΠΊΠ°ΡΠ½ΠΎ Π΅ Π΄Π° ΡΠ΅ ΡΠΈΡΠ° Π²ΠΎ ΡΠ΅ΡΠΈΠΈΠΎΡΠΊΠΎΠ»ΠΊΡ ΡΠ°ΠΌ.
Π‘Π΅Π³Π° Π΄Π° ΡΠ΅ ΠΎΠ±ΠΈΠ΄Π΅ΠΌΠ΅ Π΄Π° Π³ΠΎ ΠΊΠΎΠ½ΡΡΡΡΠΈΡΠ°ΠΌΠ΅ Π±Π°ΡΠ°ΡΠ΅ΡΠΎ ΡΡΠΎ Π½ΠΈ ΡΡΠ΅Π±Π°.
Π§Π΅ΠΊΠΎΡ 1
ΠΡΠΈΠ³Π»Π΅Π΄Π½ΠΎ, ΠΏΡΠΈ ΠΈΠ½ΠΈΡΠΈΡΠ°Π»ΠΈΠ·ΠΈΡΠ°ΡΠ΅ Π½Π° ΡΠ΅ΠΊΡΡΠ·ΠΈΡΠ°ΡΠ° (ΠΊΠ°Π΄Π΅ ΡΠ΅ Π±Π΅Π²ΠΌΠ΅ Π±Π΅Π· Π½Π΅Π°!) ΡΠ΅ ΡΡΠ΅Π±Π° Π΄Π° Π³ΠΈ ΠΎΠ΄Π·Π΅ΠΌΠ΅ΠΌΠ΅ Π·Π°ΠΏΠΈΡΠΈΡΠ΅ Π½Π° ΡΠ°ΠΌΠΈΡΠ΅ Π»ΠΈΡΡΠΎΠ²ΠΈ Π²ΡΠ· ΠΎΡΠ½ΠΎΠ²Π° Π½Π° ΠΌΠ½ΠΎΠΆΠ΅ΡΡΠ²ΠΎΡΠΎ ΠΏΠΎΡΠ΅ΡΠ½ΠΈ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΠΈ:
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
, Π½ΠΎ Π½Π΅ ΠΈ Π·Π° Π½ΠΈΠ·ΠΈ. ΠΠ°ΠΊΠΎ ΡΠ°Π°
Π§Π΅ΠΊΠΎΡ 2
Π‘Π΅Π³Π° ΡΠ΅ Π΄ΠΎΠ±ΠΈΠ΅ΠΌΠ΅ Π·Π±ΠΈΡ Π½Π° ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΠΈ Π½Π° ΡΠ΅ΠΊΡΠΈΠΈ ΠΊΠΎΠΈ ΡΠ΅ ΡΡΠ΅Π±Π° Π΄Π° ΡΠ΅ ΠΏΡΠΎΡΠΈΡΠ°Π°Ρ ΠΏΠΎΠ½Π°ΡΠ°ΠΌΡ. Π Π΅ΡΠΈΡΠΈ ΡΠ΅ΠΊΠΎΠ³Π°Ρ ΡΠΈΠ΅ ΡΠ΅ Π±ΠΈΠ΄Π°Ρ Π΄ΡΠΏΠ»ΠΈΡΠ°Π½ΠΈ Π²ΠΎ ΡΠ°Π·Π»ΠΈΡΠ½ΠΈ Π·Π°ΠΏΠΈΡΠΈ ΠΎΠ΄ ΠΎΡΠΈΠ³ΠΈΠ½Π°Π»Π½ΠΈΠΎΡ ΡΠ΅Ρ - ΡΠ°ΠΊΠ° ΠΈ Π½ΠΈΠ΅ Π±ΠΈ Π³ΡΡΠΏΠΈΡΠ°ΡΡΠ΅ Π³ΠΈ, ΠΏΡΠΈΡΠΎΠ° Π·Π°ΡΡΠ²ΡΠ²Π°ΡΡΠΈ Π³ΠΈ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΠΈΡΠ΅ Π·Π° ΠΈΠ·Π²ΠΎΡΠ½ΠΈΡΠ΅ Π»ΠΈΡΡΠΎΠ²ΠΈ.
ΠΠΎ, ΡΡΠΊΠ° Π½Π΅ ΡΠ΅ΠΊΠ°Π°Ρ ΡΡΠΈ Π½Π΅Π²ΠΎΠ»ΡΠΈ:
- βΠ‘ΡΠ±ΡΠ΅ΠΊΡΡΠ·ΠΈΠ²Π½ΠΈΠΎΡβ Π΄Π΅Π» ΠΎΠ΄ Π±Π°ΡΠ°ΡΠ΅ΡΠΎ Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠΎΠ΄ΡΠΆΠΈ Π·Π±ΠΈΡΠ½ΠΈ ΡΡΠ½ΠΊΡΠΈΠΈ ΡΠΎ
GROUP BY
. - Π Π΅ΡΠ΅ΡΠ΅Π½ΡΠ°ΡΠ° Π·Π° ΡΠ΅ΠΊΡΡΠ·ΠΈΠ²Π½Π° βΡΠ°Π±Π΅Π»Π°β Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° Π±ΠΈΠ΄Π΅ Π²ΠΎ Π²Π³Π½Π΅Π·Π΄Π΅Π½ΠΎ ΠΏΠΎΠ΄ΠΏΡΠ°ΡΠ°ΡΠ΅.
- ΠΠ°ΡΠ°ΡΠ΅ΡΠΎ Π²ΠΎ ΡΠ΅ΠΊΡΡΠ·ΠΈΠ²Π½ΠΈΠΎΡ Π΄Π΅Π» Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠΎΠ΄ΡΠΆΠΈ CTE.
ΠΠ° ΡΡΠ΅ΡΠ°, ΡΠΈΡΠ΅ ΠΎΠ²ΠΈΠ΅ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠΈ ΡΠ΅ ΠΏΡΠΈΠ»ΠΈΡΠ½ΠΎ Π»Π΅ΡΠ½ΠΈ Π·Π° ΡΠ΅ΡΠ°Π²Π°ΡΠ΅. ΠΠ° ΠΏΠΎΡΠ½Π΅ΠΌΠ΅ ΠΎΠ΄ ΠΊΡΠ°ΡΠΎΡ.
CTE Π²ΠΎ ΡΠ΅ΠΊΡΡΠ·ΠΈΠ²Π΅Π½ Π΄Π΅Π»
ΠΠ²Π΄Π΅, ΡΠ°ΠΊΠ° ΠΠ΅ΠΌΠ° ΡΠ°Π±ΠΎΡΠΈ:
WITH RECURSIVE tree AS (
...
UNION ALL
WITH T (...)
SELECT ...
)
Π ΡΠ°ΠΊΠ° ΡΡΠ½ΠΊΡΠΈΠΎΠ½ΠΈΡΠ°, Π·Π°Π³ΡΠ°Π΄ΠΈΡΠ΅ ΡΠ° ΠΏΡΠ°Π²Π°Ρ ΡΠ°Π·Π»ΠΈΠΊΠ°ΡΠ°!
WITH RECURSIVE tree AS (
...
UNION ALL
(
WITH T (...)
SELECT ...
)
)
ΠΠ³Π½Π΅Π·Π΄Π΅Π½ΠΎ Π±Π°ΡΠ°ΡΠ΅ ΠΏΡΠΎΡΠΈΠ² ΡΠ΅ΠΊΡΡΠ·ΠΈΠ²Π½Π° βΡΠ°Π±Π΅Π»Π°β
Π₯ΠΌ... ΠΠ΅ ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ ΠΏΡΠΈΡΡΠ°ΠΏΠΈ Π΄ΠΎ ΡΠ΅ΠΊΡΡΠ·ΠΈΠ²Π΅Π½ CTE Π²ΠΎ ΠΏΠΎΠ΄ΠΏΡΠ°ΡΠ°ΡΠ΅. ΠΠΎ, ΡΠΎΠ° ΠΌΠΎΠΆΠ΅ Π΄Π° Π±ΠΈΠ΄Π΅ Π²ΠΎ CTE! Π Π²Π³Π½Π΅Π·Π΄Π΅Π½ΠΎΡΠΎ Π±Π°ΡΠ°ΡΠ΅ Π²Π΅ΡΠ΅ ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΏΡΠΈΡΡΠ°ΠΏΠΈ Π΄ΠΎ ΠΎΠ²ΠΎΡ CTE!
ΠΠ Π£ΠΠ ΠΠ Π²Π½Π°ΡΡΠ΅ ΡΠ΅ΠΊΡΡΠ·ΠΈΡΠ°
ΠΠ΅ΠΏΡΠΈΡΠ°ΡΠ½ΠΎ Π΅, Π½ΠΎ... ΠΠΌΠ°ΠΌΠ΅ Π΅Π΄Π½ΠΎΡΡΠ°Π²Π΅Π½ Π½Π°ΡΠΈΠ½ Π΄Π° ΡΠ° ΠΈΠΌΠΈΡΠΈΡΠ°ΠΌΠ΅ GROUP BY 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
Π‘Π΅Π³Π° Π³Π»Π΅Π΄Π°ΠΌΠ΅ Π·ΠΎΡΡΠΎ Π½ΡΠΌΠ΅ΡΠΈΡΠΊΠΈΠΎΡ ID Π΅ ΠΏΡΠ΅ΡΠ²ΠΎΡΠ΅Π½ Π²ΠΎ ΡΠ΅ΠΊΡΡ - Π·Π° Π΄Π° ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ ΡΠΏΠΎΡΠ°Ρ, ΡΠ°Π·Π΄Π΅Π»Π΅Π½ΠΈ ΡΠΎ Π·Π°ΠΏΠΈΡΠΊΠΈ!
Π§Π΅ΠΊΠΎΡ 3
ΠΠ° ΡΠΈΠ½Π°Π»Π΅ΡΠΎ Π½Π΅ Π½ΠΈ ΠΏΡΠ΅ΠΎΡΡΠ°Π½ΡΠ²Π° Π½ΠΈΡΡΠΎ:
- ΡΠΈΡΠ°ΠΌΠ΅ Π·Π°ΠΏΠΈΡΠΈ βΡΠ΅ΠΊΡΠΈΡΠ°β Π²ΡΠ· ΠΎΡΠ½ΠΎΠ²Π° Π½Π° Π·Π±ΠΈΡ Π½Π° Π³ΡΡΠΏΠΈΡΠ°Π½ΠΈ ID
- Π³ΠΈ ΡΠΏΠΎΡΠ΅Π΄ΡΠ²Π°ΠΌΠ΅ ΠΎΠ΄Π·Π΅ΠΌΠ΅Π½ΠΈΡΠ΅ Π΄Π΅Π»ΠΎΠ²ΠΈ ΡΠΎ βΠΌΠ½ΠΎΠΆΠ΅ΡΡΠ²Π°ΡΠ°β Π½Π° ΠΎΡΠΈΠ³ΠΈΠ½Π°Π»Π½ΠΈΡΠ΅ Π»ΠΈΡΡΠΎΠ²ΠΈ
- βΠΏΡΠΎΡΠΈΡΠ΅ΡΠ΅ ΡΠ°β Π½ΠΈΠ·Π°ΡΠ° ΡΠΎ ΠΌΠ½ΠΎΠΆΠ΅ΡΡΠ²Π° ΠΊΠΎΡΠΈΡΡΠ΅ΡΡΠΈ
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;
ΠΠ·Π²ΠΎΡ: www.habr.com