ΠΠ½Ρ‚ΠΈΡˆΠ΅ΠΌΠΈ Π½Π° PostgreSQL: ΠšΠΎΠ»ΠΊΡƒ Π΅ Π΄Π»Π°Π±ΠΎΠΊΠ° Π΄ΡƒΠΏΠΊΠ°Ρ‚Π° Π·Π° Π·Π°Ρ˜Π°ΠΊΠΎΡ‚? ајдС Π΄Π° ΠΏΠΎΠΌΠΈΠ½Π΅ΠΌΠ΅ Π½ΠΈΠ· Ρ…ΠΈΠ΅Ρ€Π°Ρ€Ρ…ΠΈΡ˜Π°Ρ‚Π°

Π’ΠΎ слоТСни ERP систСми ΠΌΠ½ΠΎΠ³Ρƒ Π΅Π½Ρ‚ΠΈΡ‚Π΅Ρ‚ΠΈ ΠΈΠΌΠ°Π°Ρ‚ хиСрархиска ΠΏΡ€ΠΈΡ€ΠΎΠ΄Π°ΠΊΠΎΠ³Π° сС Ρ€Π΅Π΄Π°Ρ‚ Ρ…ΠΎΠΌΠΎΠ³Π΅Π½ΠΈ ΠΏΡ€Π΅Π΄ΠΌΠ΅Ρ‚ΠΈ Π΄Ρ€Π²ΠΎ Π½Π° односитС ΠΏΡ€Π΅Π΄ΠΎΠΊ-ΠΏΠΎΡ‚ΠΎΠΌΠΎΠΊ - ΠΎΠ²Π° Π΅ организациската структура Π½Π° ΠΏΡ€Π΅Ρ‚ΠΏΡ€ΠΈΡ˜Π°Ρ‚ΠΈΠ΅Ρ‚ΠΎ (ситС ΠΎΠ²ΠΈΠ΅ Π³Ρ€Π°Π½ΠΊΠΈ, оддСлСнија ΠΈ Ρ€Π°Π±ΠΎΡ‚Π½ΠΈ Π³Ρ€ΡƒΠΏΠΈ), ΠΈ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³ΠΎΡ‚ Π½Π° стоки, ΠΈ областитС Π½Π° Ρ€Π°Π±ΠΎΡ‚Π°, ΠΈ Π³Π΅ΠΎΠ³Ρ€Π°Ρ„ΠΈΡ˜Π°Ρ‚Π° Π½Π° ΠΏΡ€ΠΎΠ΄Π°ΠΆΠ½ΠΈΡ‚Π΅ мСста,...

ΠΠ½Ρ‚ΠΈΡˆΠ΅ΠΌΠΈ Π½Π° PostgreSQL: ΠšΠΎΠ»ΠΊΡƒ Π΅ Π΄Π»Π°Π±ΠΎΠΊΠ° Π΄ΡƒΠΏΠΊΠ°Ρ‚Π° Π·Π° Π·Π°Ρ˜Π°ΠΊΠΎΡ‚? ајдС Π΄Π° ΠΏΠΎΠΌΠΈΠ½Π΅ΠΌΠ΅ Π½ΠΈΠ· Ρ…ΠΈΠ΅Ρ€Π°Ρ€Ρ…ΠΈΡ˜Π°Ρ‚Π°

Π’ΡΡƒΡˆΠ½ΠΎΡΡ‚, Π½Π΅ постои области Π·Π° бизнис Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΠ·Π°Ρ†ΠΈΡ˜Π°, ΠΊΠ°Π΄Π΅ ΡˆΡ‚ΠΎ ΠΊΠ°ΠΊΠΎ Ρ€Π΅Π·ΡƒΠ»Ρ‚Π°Ρ‚ Π½Π΅ Π±ΠΈ ΠΈΠΌΠ°Π»ΠΎ Π½ΠΈΠΊΠ°ΠΊΠ²Π° Ρ…ΠΈΠ΅Ρ€Π°Ρ€Ρ…ΠΈΡ˜Π°. Но, Π΄ΡƒΡ€ΠΈ ΠΈ Π°ΠΊΠΎ Π½Π΅ Ρ€Π°Π±ΠΎΡ‚ΠΈΡ‚Π΅ β€žΠ·Π° Π±ΠΈΠ·Π½ΠΈΡΠΎΡ‚β€œ, сСпак ΠΌΠΎΠΆΠ΅Ρ‚Π΅ лСсно Π΄Π° Π½Π°ΠΈΠ΄Π΅Ρ‚Π΅ Π½Π° хиСрархиски односи. НСобично Π΅, Π΄ΡƒΡ€ΠΈ ΠΈ Π²Π°ΡˆΠ΅Ρ‚ΠΎ сСмСјно стСбло ΠΈΠ»ΠΈ ΠΏΠ»Π°Π½ΠΎΡ‚ Π½Π° просториитС Π²ΠΎ трговски Ρ†Π΅Π½Ρ‚Π°Ρ€ сС со иста структура.

ΠŸΠΎΡΡ‚ΠΎΡ˜Π°Ρ‚ ΠΌΠ½ΠΎΠ³Ρƒ Π½Π°Ρ‡ΠΈΠ½ΠΈ Π·Π° ΡΠΊΠ»Π°Π΄ΠΈΡ€Π°ΡšΠ΅ Π½Π° Ρ‚Π°ΠΊΠ²ΠΎ Π΄Ρ€Π²ΠΎ Π²ΠΎ DBMS, Π½ΠΎ дСнСс ќС сС фокусирамС Π½Π° само Π΅Π΄Π½Π° ΠΎΠΏΡ†ΠΈΡ˜Π°:

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

Π—Π° ΠΎΠ²ΠΈΠ΅ ΠΏΡ€Π°ΡˆΠ°ΡšΠ° Π³ΠΎ користСвмС Ρ‚ΠΈΠΏΠΈΡ‡Π½ΠΎΡ‚ΠΎ Ρ€Π΅ΠΊΡƒΡ€Π·ΠΈΠ²Π΅Π½ JOIN:
ΠΠ½Ρ‚ΠΈΡˆΠ΅ΠΌΠΈ Π½Π° 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: ΠšΠΎΠ»ΠΊΡƒ Π΅ Π΄Π»Π°Π±ΠΎΠΊΠ° Π΄ΡƒΠΏΠΊΠ°Ρ‚Π° Π·Π° Π·Π°Ρ˜Π°ΠΊΠΎΡ‚? ајдС Π΄Π° ΠΏΠΎΠΌΠΈΠ½Π΅ΠΌΠ΅ Π½ΠΈΠ· Ρ…ΠΈΠ΅Ρ€Π°Ρ€Ρ…ΠΈΡ˜Π°Ρ‚Π°
[ΠΏΠΎΠ³Π»Π΅Π΄Π½Π΅Ρ‚Π΅ Π½Π° ΠΎΠ±Ρ˜Π°ΡΠ½ΡƒΠ²Π°ΡšΠ΅.tensor.ru]

ΠžΡ‡Π΅ΠΊΡƒΠ²Π°Π½ΠΎ Π³ΠΈ најдовмС ситС 30 записи. Но, Ρ‚ΠΈΠ΅ ΠΏΠΎΡ‚Ρ€ΠΎΡˆΠΈΡ˜Π° 60% ΠΎΠ΄ Π²ΠΊΡƒΠΏΠ½ΠΎΡ‚ΠΎ Π²Ρ€Π΅ΠΌΠ΅ Π½Π° ΠΎΠ²Π° - Π·Π°Ρ‚ΠΎΠ° ΡˆΡ‚ΠΎ Π½Π°ΠΏΡ€Π°Π²ΠΈΡ˜Π° ΠΈ 30 ΠΏΡ€Π΅Π±Π°Ρ€ΡƒΠ²Π°ΡšΠ° Π²ΠΎ индСксот. Π”Π°Π»ΠΈ Π΅ ΠΌΠΎΠΆΠ½ΠΎ Π΄Π° сС Π½Π°ΠΏΡ€Π°Π²ΠΈ ΠΏΠΎΠΌΠ°Π»ΠΊΡƒ?

Масовно Π»Π΅ΠΊΡ‚ΠΎΡ€ΠΈΡ€Π°ΡšΠ΅ ΠΏΠΎ индСкс

Π”Π°Π»ΠΈ Ρ‚Ρ€Π΅Π±Π° Π΄Π° Π½Π°ΠΏΡ€Π°Π²ΠΈΠΌΠ΅ посСбно индСксно Π±Π°Ρ€Π°ΡšΠ΅ Π·Π° сСкој јазол? Π˜Π·Π»Π΅Π³ΡƒΠ²Π° Π΄Π΅ΠΊΠ° Π½Π΅ - ΠΌΠΎΠΆΠ΅ΠΌΠ΅ Π΄Π° ΠΏΡ€ΠΎΡ‡ΠΈΡ‚Π°ΠΌΠ΅ ΠΎΠ΄ индСксот ΠΊΠΎΡ€ΠΈΡΡ‚Π΅Ρ˜ΡœΠΈ Π½Π΅ΠΊΠΎΠ»ΠΊΡƒ ΠΊΠΎΠΏΡ‡ΠΈΡšΠ° одСднаш Π²ΠΎ Π΅Π΄Π΅Π½ ΠΏΠΎΠ²ΠΈΠΊ со помош Π½Π° = ANY(array).

И Π²ΠΎ сСкоја Ρ‚Π°ΠΊΠ²Π° Π³Ρ€ΡƒΠΏΠ° Π½Π° ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΠΈ ΠΌΠΎΠΆΠ΅ΠΌΠ΅ Π΄Π° Π³ΠΈ Π·Π΅ΠΌΠ΅ΠΌΠ΅ ситС ID-ΠΈ ΠΏΡ€ΠΎΠ½Π°Ρ˜Π΄Π΅Π½ΠΈ Π²ΠΎ ΠΏΡ€Π΅Ρ‚Ρ…ΠΎΠ΄Π½ΠΈΠΎΡ‚ Ρ‡Π΅ΠΊΠΎΡ€ ΠΏΠΎ β€žΡ˜Π°Π·Π»ΠΈβ€œ. Π’ΠΎΠ° Π΅, Π½Π° сСкој слСдСн Ρ‡Π΅ΠΊΠΎΡ€ Π½ΠΈΠ΅ ќС ΠΏΠΎΠ±Π°Ρ€Π°Ρ˜Ρ‚Π΅ Π³ΠΈ ситС ΠΏΠΎΡ‚ΠΎΠΌΡ†ΠΈ Π½Π° ΠΎΠ΄Ρ€Π΅Π΄Π΅Π½ΠΎ Π½ΠΈΠ²ΠΎ одСднаш.

Π‘Π°ΠΌΠΎ, Ρ‚ΡƒΠΊΠ° Π΅ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΎΡ‚, Π²ΠΎ Ρ€Π΅ΠΊΡƒΡ€Π·ΠΈΠ²Π΅Π½ ΠΈΠ·Π±ΠΎΡ€, Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° си пристапитС Π²ΠΎ Π²Π³Π½Π΅Π·Π΄Π΅Π½ΠΎ Π±Π°Ρ€Π°ΡšΠ΅, Π½ΠΎ Ρ‚Ρ€Π΅Π±Π° Π½Π΅ΠΊΠ°ΠΊΠΎ Π΄Π° Π³ΠΎ ΠΈΠ·Π±Π΅Ρ€Π΅ΠΌΠ΅ само ΠΎΠ½Π° ΡˆΡ‚ΠΎ Π΅ ΠΏΡ€ΠΎΠ½Π°Ρ˜Π΄Π΅Π½ΠΎ Π½Π° ΠΏΡ€Π΅Ρ‚Ρ…ΠΎΠ΄Π½ΠΎΡ‚ΠΎ Π½ΠΈΠ²ΠΎ... Π˜Π·Π»Π΅Π³ΡƒΠ²Π° Π΄Π΅ΠΊΠ° Π΅ Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ Π΄Π° сС Π½Π°ΠΏΡ€Π°Π²ΠΈ Π²Π³Π½Π΅Π·Π΄Π΅Π½ΠΎ Π±Π°Ρ€Π°ΡšΠ΅ Π·Π° Ρ†Π΅Π»ΠΈΠΎΡ‚ ΠΈΠ·Π±ΠΎΡ€, Π½ΠΎ Π·Π° Π½Π΅Π³ΠΎΠ²ΠΎΡ‚ΠΎ спСцифично ΠΏΠΎΠ»Π΅ Π΅ ΠΌΠΎΠΆΠ½ΠΎ. И ΠΎΠ²Π° ΠΏΠΎΠ»Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° Π±ΠΈΠ΄Π΅ ΠΈ Π½ΠΈΠ·Π° - ΡˆΡ‚ΠΎ Π΅ ΠΎΠ½Π° ΡˆΡ‚ΠΎ Ρ‚Ρ€Π΅Π±Π° Π΄Π° Π³ΠΎ користимС 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: ΠšΠΎΠ»ΠΊΡƒ Π΅ Π΄Π»Π°Π±ΠΎΠΊΠ° Π΄ΡƒΠΏΠΊΠ°Ρ‚Π° Π·Π° Π·Π°Ρ˜Π°ΠΊΠΎΡ‚? ајдС Π΄Π° ΠΏΠΎΠΌΠΈΠ½Π΅ΠΌΠ΅ Π½ΠΈΠ· Ρ…ΠΈΠ΅Ρ€Π°Ρ€Ρ…ΠΈΡ˜Π°Ρ‚Π°
[ΠΏΠΎΠ³Π»Π΅Π΄Π½Π΅Ρ‚Π΅ Π½Π° ΠΎΠ±Ρ˜Π°ΡΠ½ΡƒΠ²Π°ΡšΠ΅.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: ΠšΠΎΠ»ΠΊΡƒ Π΅ Π΄Π»Π°Π±ΠΎΠΊΠ° Π΄ΡƒΠΏΠΊΠ°Ρ‚Π° Π·Π° Π·Π°Ρ˜Π°ΠΊΠΎΡ‚? ајдС Π΄Π° ΠΏΠΎΠΌΠΈΠ½Π΅ΠΌΠ΅ Π½ΠΈΠ· Ρ…ΠΈΠ΅Ρ€Π°Ρ€Ρ…ΠΈΡ˜Π°Ρ‚Π°
[ΠΏΠΎΠ³Π»Π΅Π΄Π½Π΅Ρ‚Π΅ Π½Π° ΠΎΠ±Ρ˜Π°ΡΠ½ΡƒΠ²Π°ΡšΠ΅.tensor.ru]

УспСавмС Π΄Π° Π½Π°ΠΌΠ°Π»ΠΈΠΌΠ΅ ΡƒΡˆΡ‚Π΅ Π΅Π΄Π΅Π½ индСксСн ΠΏΠΎΠ²ΠΈΠΊ ΠΈ освои повСќС ΠΎΠ΄ 2 ΠΏΠ°Ρ‚ΠΈ Π²ΠΎ ΠΎΠ±Π΅ΠΌ Π»Π΅ΠΊΡ‚ΠΎΡ€ΠΈΡ€Π°Π½ΠΈ.

#2. Π”Π° сС ​​вратимС Π½Π° ΠΊΠΎΡ€Π΅Π½ΠΈΡ‚Π΅

Овој Π°Π»Π³ΠΎΡ€ΠΈΡ‚Π°ΠΌ ќС Π±ΠΈΠ΄Π΅ корисСн Π°ΠΊΠΎ Ρ‚Ρ€Π΅Π±Π° Π΄Π° собСрСтС записи Π·Π° ситС Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ΠΈ β€žΠ³ΠΎΡ€Π΅ Π½Π° Π΄Ρ€Π²ΠΎΡ‚ΠΎβ€œ, ΠΏΡ€ΠΈΡ‚ΠΎΠ° Π·Π°Π΄Ρ€ΠΆΡƒΠ²Π°Ρ˜ΡœΠΈ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ Π·Π° Ρ‚ΠΎΠ° кој ΠΈΠ·Π²ΠΎΡ€Π΅Π½ лист (ΠΈ со ΠΊΠΎΠΈ ΠΈΠ½Π΄ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΠΈ) Π³ΠΎ ΠΏΡ€Π΅Π΄ΠΈΠ·Π²ΠΈΠΊΠ°Π» Ρ‚ΠΎΡ˜ Π΄Π° Π±ΠΈΠ΄Π΅ Π²ΠΊΠ»ΡƒΡ‡Π΅Π½ Π²ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΎΠΊΠΎΡ‚ - Π½Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π΄Π° Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π° Π·Π±ΠΈΡ€Π΅Π½ ΠΈΠ·Π²Π΅ΡˆΡ‚Π°Ρ˜ со Π°Π³Ρ€Π΅Π³Π°Ρ†ΠΈΡ˜Π° Π²ΠΎ јазли.

ΠΠ½Ρ‚ΠΈΡˆΠ΅ΠΌΠΈ Π½Π° PostgreSQL: ΠšΠΎΠ»ΠΊΡƒ Π΅ Π΄Π»Π°Π±ΠΎΠΊΠ° Π΄ΡƒΠΏΠΊΠ°Ρ‚Π° Π·Π° Π·Π°Ρ˜Π°ΠΊΠΎΡ‚? ајдС Π΄Π° ΠΏΠΎΠΌΠΈΠ½Π΅ΠΌΠ΅ Π½ΠΈΠ· Ρ…ΠΈΠ΅Ρ€Π°Ρ€Ρ…ΠΈΡ˜Π°Ρ‚Π°
Она ΡˆΡ‚ΠΎ слСди Ρ‚Ρ€Π΅Π±Π° Π΄Π° сС Π·Π΅ΠΌΠ΅ само ΠΊΠ°ΠΊΠΎ Π΄ΠΎΠΊΠ°Π· Π·Π° ΠΊΠΎΠ½Ρ†Π΅ΠΏΡ‚, бидСјќи Π±Π°Ρ€Π°ΡšΠ΅Ρ‚ΠΎ сС ΠΏΠΎΠΊΠ°ΠΆΡƒΠ²Π° ΠΊΠ°ΠΊΠΎ ΠΌΠ½ΠΎΠ³Ρƒ Π½Π΅Π·Π³ΠΎΠ΄Π½ΠΎ. Но, Π°ΠΊΠΎ Π΄ΠΎΠΌΠΈΠ½ΠΈΡ€Π° Π²ΠΎ Π²Π°ΡˆΠ°Ρ‚Π° Π±Π°Π·Π° Π½Π° ΠΏΠΎΠ΄Π°Ρ‚ΠΎΡ†ΠΈ, Ρ‚Ρ€Π΅Π±Π° Π΄Π° размислитС Π·Π° ΠΊΠΎΡ€ΠΈΡΡ‚Π΅ΡšΠ΅ слични Ρ‚Π΅Ρ…Π½ΠΈΠΊΠΈ.

Π”Π° ΠΏΠΎΡ‡Π½Π΅ΠΌΠ΅ со Π½Π΅ΠΊΠΎΠ»ΠΊΡƒ Сдноставни изјави:

  • Π˜ΡΡ‚ΠΈΠΎΡ‚ запис ΠΎΠ΄ Π±Π°Π·Π°Ρ‚Π° Π½Π° ΠΏΠΎΠ΄Π°Ρ‚ΠΎΡ†ΠΈ ΠΠ°Ρ˜Π΄ΠΎΠ±Ρ€ΠΎ Π΅ Π΄Π° Π³ΠΎ ΠΏΡ€ΠΎΡ‡ΠΈΡ‚Π°Ρ‚Π΅ само Сднаш.
  • Записи ΠΎΠ΄ Π±Π°Π·Π°Ρ‚Π° Π½Π° ΠΏΠΎΠ΄Π°Ρ‚ΠΎΡ†ΠΈ ΠŸΠΎΠ΅Ρ„ΠΈΠΊΠ°ΡΠ½ΠΎ Π΅ Π΄Π° сС Ρ‡ΠΈΡ‚Π° Π²ΠΎ сСрииотколку сам.

Π‘Π΅Π³Π° Π΄Π° сС ΠΎΠ±ΠΈΠ΄Π΅ΠΌΠ΅ Π΄Π° Π³ΠΎ конструирамС Π±Π°Ρ€Π°ΡšΠ΅Ρ‚ΠΎ ΡˆΡ‚ΠΎ Π½ΠΈ Ρ‚Ρ€Π΅Π±Π°.

Π§Π΅ΠΊΠΎΡ€ 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

Π‘Π΅Π³Π° ќС Π΄ΠΎΠ±ΠΈΠ΅ΠΌΠ΅ Π·Π±ΠΈΡ€ Π½Π° ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΠΈ Π½Π° сСкции ΠΊΠΎΠΈ ќС Ρ‚Ρ€Π΅Π±Π° Π΄Π° сС ΠΏΡ€ΠΎΡ‡ΠΈΡ‚Π°Π°Ρ‚ ΠΏΠΎΠ½Π°Ρ‚Π°ΠΌΡƒ. РСчиси сСкогаш Ρ‚ΠΈΠ΅ ќС Π±ΠΈΠ΄Π°Ρ‚ Π΄ΡƒΠΏΠ»ΠΈΡ€Π°Π½ΠΈ Π²ΠΎ Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ записи ΠΎΠ΄ ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»Π½ΠΈΠΎΡ‚ сСт - Ρ‚Π°ΠΊΠ° ΠΈ Π½ΠΈΠ΅ Π±ΠΈ Π³Ρ€ΡƒΠΏΠΈΡ€Π°Ρ˜Ρ‚Π΅ Π³ΠΈ, ΠΏΡ€ΠΈΡ‚ΠΎΠ° Π·Π°Ρ‡ΡƒΠ²ΡƒΠ²Π°Ρ˜ΡœΠΈ Π³ΠΈ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈΡ‚Π΅ Π·Π° ΠΈΠ·Π²ΠΎΡ€Π½ΠΈΡ‚Π΅ листови.

Но, Ρ‚ΡƒΠΊΠ° Π½Π΅ Ρ‡Π΅ΠΊΠ°Π°Ρ‚ Ρ‚Ρ€ΠΈ нСволји:

  1. β€žΠ‘ΡƒΠ±Ρ€Π΅ΠΊΡƒΡ€Π·ΠΈΠ²Π½ΠΈΠΎΡ‚β€œ Π΄Π΅Π» ΠΎΠ΄ Π±Π°Ρ€Π°ΡšΠ΅Ρ‚ΠΎ Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° содрТи Π·Π±ΠΈΡ€Π½ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ со GROUP BY.
  2. Π Π΅Ρ„Π΅Ρ€Π΅Π½Ρ†Π°Ρ‚Π° Π·Π° Ρ€Π΅ΠΊΡƒΡ€Π·ΠΈΠ²Π½Π° β€žΡ‚Π°Π±Π΅Π»Π°β€œ Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° Π±ΠΈΠ΄Π΅ Π²ΠΎ Π²Π³Π½Π΅Π·Π΄Π΅Π½ΠΎ ΠΏΠΎΠ΄ΠΏΡ€Π°ΡˆΠ°ΡšΠ΅.
  3. Π‘Π°Ρ€Π°ΡšΠ΅Ρ‚ΠΎ Π²ΠΎ Ρ€Π΅ΠΊΡƒΡ€Π·ΠΈΠ²Π½ΠΈΠΎΡ‚ Π΄Π΅Π» Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° содрТи 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;

ΠΠ½Ρ‚ΠΈΡˆΠ΅ΠΌΠΈ Π½Π° PostgreSQL: ΠšΠΎΠ»ΠΊΡƒ Π΅ Π΄Π»Π°Π±ΠΎΠΊΠ° Π΄ΡƒΠΏΠΊΠ°Ρ‚Π° Π·Π° Π·Π°Ρ˜Π°ΠΊΠΎΡ‚? ајдС Π΄Π° ΠΏΠΎΠΌΠΈΠ½Π΅ΠΌΠ΅ Π½ΠΈΠ· Ρ…ΠΈΠ΅Ρ€Π°Ρ€Ρ…ΠΈΡ˜Π°Ρ‚Π°
[ΠΏΠΎΠ³Π»Π΅Π΄Π½Π΅Ρ‚Π΅ Π½Π° ΠΎΠ±Ρ˜Π°ΡΠ½ΡƒΠ²Π°ΡšΠ΅.tensor.ru]

Π˜Π·Π²ΠΎΡ€: www.habr.com

Π”ΠΎΠ΄Π°Π΄Π΅Ρ‚Π΅ ΠΊΠΎΠΌΠ΅Π½Ρ‚Π°Ρ€