Π ΡΠ»ΠΎΠΆΠ½ΡΡ 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)
.
Π Π² ΠΊΠ°ΠΆΠ΄ΡΡ ΡΠ°ΠΊΡΡ Π³ΡΡΠΏΠΏΡ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΠΎΠ² ΠΌΡ ΠΌΠΎΠΆΠ΅ΠΌ Π²Π·ΡΡΡ Π²ΡΠ΅ Π½Π°ΠΉΠ΄Π΅Π½Π½ΡΠ΅ Π½Π° ΠΏΡΠ΅Π΄ΡΠ΄ΡΡΠ΅ΠΌ ΡΠ°Π³Π΅ 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 ΡΠ°Π·Π° ΠΏΠΎ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ, Π° ΡΡΠΎ ΠΌΡ Π²ΡΡΠΈΡΠ°Π»ΠΈ ΠΌΠ΅Π½ΡΡΠ΅ buffers, ΠΏΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΠΎΠ±ΡΠ°ΡΠ΅Π½ΠΈΠΉ ΠΊ ΠΈΠ½Π΄Π΅ΠΊΡΡ Ρ Π½Π°Ρ Π²ΡΠ΅Π³ΠΎ 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. ΠΠ΅ΡΠ½Π΅ΠΌΡΡ ΠΊ ΠΊΠΎΡΠ½ΡΠΌ
ΠΡΠΎΡ Π°Π»Π³ΠΎΡΠΈΡΠΌ Π±ΡΠ΄Π΅Ρ ΠΏΠΎΠ»Π΅Π·Π΅Π½, Π΅ΡΠ»ΠΈ Π²Π°ΠΌ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ ΡΠΎΠ±ΡΠ°ΡΡ Π·Π°ΠΏΠΈΡΠΈ Π΄Π»Ρ Π²ΡΠ΅Ρ ΡΠ»Π΅ΠΌΠ΅Π½ΡΠΎΠ² Β«Π²Π²Π΅ΡΡ ΠΏΠΎ Π΄Π΅ΡΠ΅Π²ΡΒ», ΡΠΎΡ ΡΠ°Π½ΠΈΠ² ΠΏΡΠΈ ΡΡΠΎΠΌ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ, ΠΊΠ°ΠΊΠΈΠΌ ΠΈΡΡ ΠΎΠ΄Π½ΡΠΌ Π»ΠΈΡΡΠΎΠΌ (ΠΈ Ρ ΠΊΠ°ΠΊΠΈΠΌΠΈ ΠΏΠΎΠΊΠ°Π·Π°ΡΠ΅Π»ΡΠΌΠΈ) Π²ΡΠ·Π²Π°Π½ΠΎ Π΅Π³ΠΎ ΠΏΠΎΠΏΠ°Π΄Π°Π½ΠΈΠ΅ Π² Π²ΡΠ±ΠΎΡΠΊΡ β Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, Π΄Π»Ρ ΡΠΎΡΠΌΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΡΠ²ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΎΡΡΠ΅ΡΠ° Ρ Π°Π³ΡΠ΅Π³Π°ΡΠΈΠ΅ΠΉ Π½Π° ΡΠ·Π»Ρ.
ΠΠ°Π»ΡΠ½Π΅ΠΉΡΠ΅Π΅ ΡΡΠΎΠΈΡ Π²ΠΎΡΠΏΡΠΈΠ½ΠΈΠΌΠ°ΡΡ ΠΈΡΠΊΠ»ΡΡΠΈΡΠ΅Π»ΡΠ½ΠΎ ΠΊΠ°ΠΊ proof-of-concept, ΠΏΠΎΡΠΊΠΎΠ»ΡΠΊΡ Π·Π°ΠΏΡΠΎΡ ΠΏΠΎΠ»ΡΡΠ°Π΅ΡΡΡ ΠΎΡΠ΅Π½Ρ ΡΠΆ Π³ΡΠΎΠΌΠΎΠ·Π΄ΠΊΠΈΠΉ. ΠΠΎ Π΅ΡΠ»ΠΈ ΠΎΠ½ Π΄ΠΎΠΌΠΈΠ½ΠΈΡΡΠ΅Ρ Π² Π²Π°ΡΠ΅ΠΉ Π±Π°Π·Π΅ β ΡΡΠΎΠΈΡ Π·Π°Π΄ΡΠΌΠ°ΡΡΡΡ Π½Π°Π΄ ΠΏΡΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ΠΌ ΠΏΠΎΠ΄ΠΎΠ±Π½ΡΡ
ΠΌΠ΅ΡΠΎΠ΄ΠΈΠΊ.
ΠΠ°ΡΠ½Π΅ΠΌ Ρ ΠΏΠ°ΡΡ ΠΏΡΠΎΡΡΡΡ ΡΡΠ²Π΅ΡΠΆΠ΄Π΅Π½ΠΈΠΉ:
- ΠΠ΄Π½Ρ ΠΈ ΡΡ ΠΆΠ΅ Π·Π°ΠΏΠΈΡΡ ΠΈΠ· Π±Π°Π·Ρ Π»ΡΡΡΠ΅ ΡΠΈΡΠ°ΡΡ Π²ΡΠ΅Π³ΠΎ ΠΎΠ΄ΠΈΠ½ ΡΠ°Π·.
- ΠΠ°ΠΏΠΈΡΠΈ ΠΈΠ· Π±Π°Π·Ρ ΡΡΡΠ΅ΠΊΡΠΈΠ²Π½Π΅Π΅ ΡΠΈΡΠ°ΡΡ Β«ΠΏΠ°ΡΠΊΠΎΠΉΒ», ΡΠ΅ΠΌ ΠΏΠΎΠΎΠ΄ΠΈΠ½ΠΎΡΠΊΠ΅.
Π’Π΅ΠΏΠ΅ΡΡ ΠΏΠΎΠΏΡΠΎΠ±ΡΠ΅ΠΌ ΡΠΊΠΎΠ½ΡΡΡΡΠΈΡΠΎΠ²Π°ΡΡ Π½ΡΠΆΠ½ΡΠΉ Π½Π°ΠΌ Π·Π°ΠΏΡΠΎΡ.
Π¨Π°Π³ 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
Π’Π΅ΠΏΠ΅ΡΡ Π½Π°ΠΌ Π±Ρ ΠΏΠΎΠ»ΡΡΠΈΡΡ Π½Π°Π±ΠΎΡ ID ΡΠ°Π·Π΄Π΅Π»ΠΎΠ², ΠΊΠΎΡΠΎΡΡΠ΅ Π½Π°Π΄ΠΎ Π±ΡΠ΄Π΅Ρ Π²ΡΡΠΈΡΠ°ΡΡ Π΄Π°Π»ΡΡΠ΅. ΠΠΎΡΡΠΈ Π²ΡΠ΅Π³Π΄Π° ΠΎΠ½ΠΈ Π±ΡΠ΄ΡΡ Π΄ΡΠ±Π»ΠΈΡΠΎΠ²Π°ΡΡΡΡ Ρ ΡΠ°Π·Π½ΡΡ Π·Π°ΠΏΠΈΡΠ΅ΠΉ ΠΈΡΡ ΠΎΠ΄Π½ΠΎΠ³ΠΎ Π½Π°Π±ΠΎΡΠ° β ΠΏΠΎΡΡΠΎΠΌΡ Π½Π°ΠΌ Π±Ρ ΠΈΡ ΡΠ³ΡΡΠΏΠΏΠΈΡΠΎΠ²Π°ΡΡ, ΡΠΎΡ ΡΠ°Π½ΠΈΠ² ΠΏΡΠΈ ΡΡΠΎΠΌ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ ΠΎ Π»ΠΈΡΡΡΡΡ -ΠΈΡΡΠΎΡΠ½ΠΈΠΊΠ°Ρ .
ΠΠΎ ΡΡΡ Π½Π°Ρ ΠΏΠΎΠ΄ΠΆΠΈΠ΄Π°ΡΡ ΡΡΠΈ Π½Π΅ΠΏΡΠΈΡΡΠ½ΠΎΡΡΠΈ:
- Β«ΠΠΎΠ΄ΡΠ΅ΠΊΡΡΡΠΈΠ²Π½Π°ΡΒ» ΡΠ°ΡΡΡ Π·Π°ΠΏΡΠΎΡΠ° Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ ΡΠΎΠ΄Π΅ΡΠΆΠ°ΡΡ Π°Π³ΡΠ΅Π³Π°ΡΠ½ΡΡ
ΡΡΠ½ΠΊΡΠΈΠΉ Ρ
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
ΠΠΎΡ ΡΠ΅ΠΏΠ΅ΡΡ ΠΌΡ Π²ΠΈΠ΄ΠΈΠΌ, Π·Π°ΡΠ΅ΠΌ ΡΠΈΡΠ»ΠΎΠ²ΠΎΠΉ 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;
ΠΡΡΠΎΡΠ½ΠΈΠΊ: habr.com