Π ΡΠ»ΠΎΠΆΠ½ΠΈ ERP ΡΠΈΡΡΠ΅ΠΌΠΈ ΠΌΠ½ΠΎΠ³ΠΎ ΡΡΠ±Π΅ΠΊΡΠΈ ΠΈΠΌΠ°Ρ ΠΉΠ΅ΡΠ°ΡΡ ΠΈΡΠ΅Π½ Ρ Π°ΡΠ°ΠΊΡΠ΅ΡΠΊΠΎΠ³Π°ΡΠΎ Ρ ΠΎΠΌΠΎΠ³Π΅Π½Π½ΠΈ ΠΎΠ±Π΅ΠΊΡΠΈ ΡΠ΅ ΠΏΠΎΠ΄ΡΠ΅Π΄ΡΡ Π² Π΄ΡΡΠ²ΠΎ Π½Π° Π²Π·Π°ΠΈΠΌΠΎΠΎΡΠ½ΠΎΡΠ΅Π½ΠΈΡΡΠ° ΠΏΡΠ΅Π΄ΡΠΈ-ΠΏΠΎΡΠΎΠΌΡΠΈ - ΡΠΎΠ²Π° Π΅ ΠΎΡΠ³Π°Π½ΠΈΠ·Π°ΡΠΈΠΎΠ½Π½Π°ΡΠ° ΡΡΡΡΠΊΡΡΡΠ° Π½Π° ΠΏΡΠ΅Π΄ΠΏΡΠΈΡΡΠΈΠ΅ΡΠΎ (Π²ΡΠΈΡΠΊΠΈ ΡΠ΅Π·ΠΈ ΠΊΠ»ΠΎΠ½ΠΎΠ²Π΅, ΠΎΡΠ΄Π΅Π»ΠΈ ΠΈ ΡΠ°Π±ΠΎΡΠ½ΠΈ Π³ΡΡΠΏΠΈ), ΠΈ ΠΊΠ°ΡΠ°Π»ΠΎΠ³ΡΡ Π½Π° ΡΡΠΎΠΊΠΈΡΠ΅, ΠΈ ΠΎΠ±Π»Π°ΡΡΠΈΡΠ΅ Π½Π° ΡΠ°Π±ΠΎΡΠ°, ΠΈ Π³Π΅ΠΎΠ³ΡΠ°ΡΠΈΡΡΠ° Π½Π° ΡΠΎΡΠΊΠΈΡΠ΅ Π·Π° ΠΏΡΠΎΠ΄Π°ΠΆΠ±Π°,...
ΠΡΡΡΠ½ΠΎΡΡ Π½ΡΠΌΠ° ΡΠ°ΠΊΡΠ²
ΠΠΌΠ° ΠΌΠ½ΠΎΠ³ΠΎ Π½Π°ΡΠΈΠ½ΠΈ Π·Π° ΡΡΡ ΡΠ°Π½ΡΠ²Π°Π½Π΅ Π½Π° ΡΠ°ΠΊΠΎΠ²Π° Π΄ΡΡΠ²ΠΎ Π² Π‘Π£ΠΠ, Π½ΠΎ Π΄Π½Π΅Ρ ΡΠ΅ ΡΠ΅ ΡΡΡΡΠ΅Π΄ΠΎΡΠΎΡΠΈΠΌ ΡΠ°ΠΌΠΎ Π²ΡΡΡ Ρ Π΅Π΄ΠΈΠ½ Π²Π°ΡΠΈΠ°Π½Ρ:
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)
.
Π Π²ΡΠ² Π²ΡΡΠΊΠ° ΡΠ°ΠΊΠ°Π²Π° Π³ΡΡΠΏΠ° ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΠΈ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° Π²Π·Π΅ΠΌΠ΅ΠΌ Π²ΡΠΈΡΠΊΠΈ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΠΈ, Π½Π°ΠΌΠ΅ΡΠ΅Π½ΠΈ Π² ΠΏΡΠ΅Π΄ΠΈΡΠ½Π°ΡΠ° ΡΡΡΠΏΠΊΠ°, ΡΡΠ΅Π· βΠ²ΡΠ·Π»ΠΈβ. Π’ΠΎΠ΅ΡΡ Π½Π° Π²ΡΡΠΊΠ° ΡΠ»Π΅Π΄Π²Π°ΡΠ° ΡΡΡΠΏΠΊΠ° ΡΠ΅ ΡΡΡΡΠ΅Π½Π΅ Π½Π° Π²ΡΠΈΡΠΊΠΈ ΠΏΠΎΡΠΎΠΌΡΠΈ Π½Π° ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΎ Π½ΠΈΠ²ΠΎ Π½Π°Π²Π΅Π΄Π½ΡΠΆ.
Π‘Π°ΠΌΠΎ ΡΠ΅ ΡΡΠΊ Π΅ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡΡ, ΠΏΡΠΈ ΡΠ΅ΠΊΡΡΡΠΈΠ²Π½Π° ΡΠ΅Π»Π΅ΠΊΡΠΈΡ Π½Π΅ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΏΠΎΠ»ΡΡΠΈΡΠ΅ Π΄ΠΎΡΡΡΠΏ Π΄ΠΎ ΡΠ΅Π±Π΅ ΡΠΈ Π²ΡΠ² Π²Π»ΠΎΠΆΠ΅Π½Π° Π·Π°ΡΠ²ΠΊΠ°, Π½ΠΎ ΡΡΡΠ±Π²Π° ΠΏΠΎ Π½ΡΠΊΠ°ΠΊΡΠ² Π½Π°ΡΠΈΠ½ Π΄Π° ΡΠ΅Π»Π΅ΠΊΡΠΈΡΠ°ΠΌΠ΅ ΡΠ°ΠΌΠΎ ΡΠΎΠ²Π°, ΠΊΠΎΠ΅ΡΠΎ Π΅ Π½Π°ΠΌΠ΅ΡΠ΅Π½ΠΎ Π½Π° ΠΏΡΠ΅Π΄ΠΈΡΠ½ΠΎΡΠΎ Π½ΠΈΠ²ΠΎ... ΠΠΊΠ°Π·Π²Π° ΡΠ΅, ΡΠ΅ Π΅ Π½Π΅Π²ΡΠ·ΠΌΠΎΠΆΠ½ΠΎ Π΄Π° ΡΠ΅ Π½Π°ΠΏΡΠ°Π²ΠΈ Π²Π»ΠΎΠΆΠ΅Π½Π° Π·Π°ΡΠ²ΠΊΠ° Π·Π° ΡΡΠ»Π°ΡΠ° ΡΠ΅Π»Π΅ΠΊΡΠΈΡ, Π½ΠΎ Π·Π° Π½Π΅ΠΉΠ½ΠΎΡΠΎ ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΠΎ ΠΏΠΎΠ»Π΅ Π΅ Π²ΡΠ·ΠΌΠΎΠΆΠ½ΠΎ. Π ΡΠΎΠ²Π° ΠΏΠΎΠ»Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° Π±ΡΠ΄Π΅ ΠΈ ΠΌΠ°ΡΠΈΠ² - ΠΊΠΎΠ΅ΡΠΎ ΡΡΡΠ±Π²Π° Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ 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!
ΠΠΎΠΏΡΠ»Π½ΠΈΡΠ΅Π»Π΅Π½ Π±ΠΎΠ½ΡΡ Π΅ ΡΠ°ΠΊΡΡΡ, ΡΠ΅ ΡΠ»Π΅Π΄ ΠΎΠΊΠΎΠ½ΡΠ°ΡΠ΅Π»Π½ΠΎΡΠΎ unnest, ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΠΈΡΠ΅ ΡΠ΅ ΠΎΡΡΠ°Π½Π°Ρ ΠΏΠΎΠ΄ΡΠ΅Π΄Π΅Π½ΠΈ ΠΏΠΎ βΠ½ΠΈΠ²Π°β.
ΠΠ½Π°ΠΊ Π·Π° Π²ΡΠ·Π΅Π»
Π‘Π»Π΅Π΄Π²Π°ΡΠΎΡΠΎ ΡΡΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠ΅, ΠΊΠΎΠ΅ΡΠΎ ΡΠ΅ ΠΏΠΎΠΌΠΎΠ³Π½Π΅ Π·Π° ΠΏΠΎΠ΄ΠΎΠ±ΡΡΠ²Π°Π½Π΅ Π½Π° ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»Π½ΠΎΡΡΡΠ°, Π΅ β "Π»ΠΈΡΡΠ°" Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΈΠΌΠ° Π΄Π΅ΡΠ°, ΡΠΎΠ΅ΡΡ Π·Π° ΡΡΡ ΠΈΠ·ΠΎΠ±ΡΠΎ Π½ΡΠΌΠ° Π½ΡΠΆΠ΄Π° Π΄Π° Π³Π»Π΅Π΄Π°Ρ βΠ½Π°Π΄ΠΎΠ»Ρβ. ΠΡΠΈ ΡΠΎΡΠΌΡΠ»ΠΈΡΠ°Π½Π΅ΡΠΎ Π½Π° Π½Π°ΡΠ°ΡΠ° Π·Π°Π΄Π°ΡΠ° ΡΠΎΠ²Π° ΠΎΠ·Π½Π°ΡΠ°Π²Π°, ΡΠ΅ Π°ΠΊΠΎ ΡΠΌΠ΅ ΡΠ»Π΅Π΄Π²Π°Π»ΠΈ Π²Π΅ΡΠΈΠ³Π°ΡΠ° ΠΎΡ ΠΎΡΠ΄Π΅Π»ΠΈ ΠΈ ΡΠΌΠ΅ ΡΡΠΈΠ³Π½Π°Π»ΠΈ Π΄ΠΎ ΡΠ»ΡΠΆΠΈΡΠ΅Π», ΡΠΎΠ³Π°Π²Π° Π½ΡΠΌΠ° Π½ΡΠΆΠ΄Π° Π΄Π° ΡΡΡΡΠΈΠΌ ΠΏΠΎ-Π½Π°ΡΠ°ΡΡΠΊ ΠΏΠΎ ΡΠΎΠ·ΠΈ ΠΊΠ»ΠΎΠ½.
ΠΠ° Π²Π»Π΅Π·Π΅ΠΌ Π² Π½Π°ΡΠ°ΡΠ° ΠΌΠ°ΡΠ° Π΄ΠΎΠΏΡΠ»Π½ΠΈΡΠ΅Π»Π΅Π½ 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 Π²ΡΡΡΠ΅ΡΠ½Π° ΡΠ΅ΠΊΡΡΡΠΈΡ
ΠΠ΅ΠΏΡΠΈΡΡΠ½ΠΎ Π΅, Π½ΠΎ... ΠΠΌΠ°ΠΌΠ΅ Π»Π΅ΡΠ΅Π½ Π½Π°ΡΠΈΠ½ Π΄Π° Π΅ΠΌΡΠ»ΠΈΡΠ°ΠΌΠ΅ 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
Π‘Π΅Π³Π° ΡΠ°Π·Π±ΠΈΡΠ°ΠΌΠ΅ Π·Π°ΡΠΎ ΡΠΈΡΠ»ΠΎΠ²ΠΈΡΡ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ Π±Π΅ΡΠ΅ ΠΏΡΠ΅Π²ΡΡΠ½Π°Ρ Π² ΡΠ΅ΠΊΡΡ - Π·Π° Π΄Π° ΠΌΠΎΠ³Π°Ρ Π΄Π° Π±ΡΠ΄Π°Ρ ΡΡΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈ Π·Π°Π΅Π΄Π½ΠΎ, ΡΠ°Π·Π΄Π΅Π»Π΅Π½ΠΈ ΡΡΡ Π·Π°ΠΏΠ΅ΡΠ°ΠΈ!
Π‘ΡΡΠΏΠΊΠ° 3
ΠΠ° ΡΠΈΠ½Π°Π» Π½Π΅ Π½ΠΈ ΠΎΡΡΠ°Π½Π° Π½ΠΈΡΠΎ:
- ΡΠ΅ΡΠ΅ΠΌ Π·Π°ΠΏΠΈΡΠΈ Π½Π° βΡΠ΅ΠΊΡΠΈΠΈβ Π²ΡΠ· ΠΎΡΠ½ΠΎΠ²Π° Π½Π° Π½Π°Π±ΠΎΡ ΠΎΡ Π³ΡΡΠΏΠΈΡΠ°Π½ΠΈ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΠΈ
- ΡΡΠ°Π²Π½ΡΠ²Π°ΠΌΠ΅ ΠΈΠ·Π²Π°Π΄Π΅Π½ΠΈΡΠ΅ ΡΠ΅ΠΊΡΠΈΠΈ Ρ βΠΊΠΎΠΌΠΏΠ»Π΅ΠΊΡΠΈΡΠ΅β Π½Π° ΠΎΡΠΈΠ³ΠΈΠ½Π°Π»Π½ΠΈΡΠ΅ Π»ΠΈΡΡΠΎΠ²Π΅
- βΡΠ°Π·ΡΠΈΡΠ΅ΡΠ΅β Π½Π°Π±ΠΎΡΠ½ΠΈΡ Π½ΠΈΠ· Ρ ΠΏΠΎΠΌΠΎΡΡΠ° Π½Π°
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