Π‘Π£ΠΠ Π² ΡΠΎΠ²Π° ΠΎΡΠ½ΠΎΡΠ΅Π½ΠΈΠ΅ ΡΠ°Π±ΠΎΡΡΡ Π½Π° ΡΡΡΠΈΡΠ΅ ΠΏΡΠΈΠ½ΡΠΈΠΏΠΈ - "ΠΠ°Π·Π°Ρ
Π° ΠΌΠΈ Π΄Π° ΠΊΠΎΠΏΠ°Ρ, Π·Π°ΡΠΎΠ²Π° ΠΊΠΎΠΏΠ°Ρ". ΠΠ°ΡΠ°ΡΠ° Π·Π°ΡΠ²ΠΊΠ° ΠΌΠΎΠΆΠ΅ Π½Π΅ ΡΠ°ΠΌΠΎ Π΄Π° Π·Π°Π±Π°Π²ΠΈ ΡΡΡΠ΅Π΄Π½ΠΈΡΠ΅ ΠΏΡΠΎΡΠ΅ΡΠΈ, ΠΏΠΎΡΡΠΎΡΠ½Π½ΠΎ Π·Π°Π΅ΠΌΠ°ΠΉΠΊΠΈ ΡΠ΅ΡΡΡΡΠΈ Π½Π° ΠΏΡΠΎΡΠ΅ΡΠΎΡΠ°, Π½ΠΎ ΠΈ Π΄Π° βΠΈΠ·ΠΏΡΡΠ½Π΅" ΡΡΠ»Π°ΡΠ° Π±Π°Π·Π° Π΄Π°Π½Π½ΠΈ, βΠΈΠ·ΡΠΆΠ΄Π°ΠΉΠΊΠΈβ ΡΡΠ»Π°ΡΠ° Π½Π°Π»ΠΈΡΠ½Π° ΠΏΠ°ΠΌΠ΅Ρ. Π‘Π»Π΅Π΄ΠΎΠ²Π°ΡΠ΅Π»Π½ΠΎ Π·Π°ΡΠΈΡΠ° ΡΡΠ΅ΡΡ Π±Π΅Π·ΠΊΡΠ°ΠΉΠ½Π° ΡΠ΅ΠΊΡΡΡΠΈΡ - ΠΎΡΠ³ΠΎΠ²ΠΎΡΠ½ΠΎΡΡ Π½Π° ΡΠ°ΠΌΠΈΡ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊ.
Π PostgreSQL Π²ΡΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡΠ° Π·Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° ΡΠ΅ΠΊΡΡΡΠΈΠ²Π½ΠΈ Π·Π°ΡΠ²ΠΊΠΈ ΡΡΠ΅Π· WITH RECURSIVE
ΠΠ΅ ΠΏΠΈΡΠ΅ΡΠ΅ ΡΠ΅ΠΊΡΡΡΠΈΠ²Π½ΠΈ Π·Π°ΡΠ²ΠΊΠΈ
Π Π½Π°ΠΏΠΈΡΠ΅ΡΠ΅ Π½Π΅ΡΠ΅ΠΊΡΡΡΠΈΠ²Π½ΠΈ. Π‘ ΡΠ²Π°ΠΆΠ΅Π½ΠΈΠ΅, ΠΠ°ΡΠΈΡΡ K.O.
ΠΡΡΡΠ½ΠΎΡΡ PostgreSQL ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Ρ Π΄ΠΎΡΡΠ° ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π»Π½ΠΎΡΡ, ΠΊΠΎΡΡΠΎ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΡΠ΅ Π½Π΅ ΠΏΡΠΈΠ»ΠΎΠΆΠΈ ΡΠ΅ΠΊΡΡΡΠΈΡ.
ΠΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΡΠ΅ ΠΏΡΠΈΠ½ΡΠΈΠΏΠ½ΠΎ ΡΠ°Π·Π»ΠΈΡΠ΅Π½ ΠΏΠΎΠ΄Ρ ΠΎΠ΄ ΠΊΡΠΌ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ°
ΠΠΎΠ½ΡΠΊΠΎΠ³Π° ΠΌΠΎΠΆΠ΅ΡΠ΅ ΠΏΡΠΎΡΡΠΎ Π΄Π° ΠΏΠΎΠ³Π»Π΅Π΄Π½Π΅ΡΠ΅ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ° ΠΎΡ βΡΠ°Π·Π»ΠΈΡΠ½Π°ΡΠ° ΡΡΡΠ°Π½Π°β. ΠΠ°Π΄ΠΎΡ
ΠΏΡΠΈΠΌΠ΅Ρ Π·Π° ΡΠ°ΠΊΠ°Π²Π° ΡΠΈΡΡΠ°ΡΠΈΡ Π² ΡΡΠ°ΡΠΈΡΡΠ°
WITH RECURSIVE src AS (
SELECT '{2,3,5,7,11,13,17,19}'::integer[] arr
)
, T(i, val) AS (
SELECT
1::bigint
, 1
UNION ALL
SELECT
i + 1
, val * arr[i]
FROM
T
, src
WHERE
i <= array_length(arr, 1)
)
SELECT
val
FROM
T
ORDER BY -- ΠΎΡΠ±ΠΎΡ ΡΠΈΠ½Π°Π»ΡΠ½ΠΎΠ³ΠΎ ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠ°
i DESC
LIMIT 1;
Π’Π°Π·ΠΈ Π·Π°ΡΠ²ΠΊΠ° ΠΌΠΎΠΆΠ΅ Π΄Π° Π±ΡΠ΄Π΅ Π·Π°ΠΌΠ΅Π½Π΅Π½Π° Ρ ΠΎΠΏΡΠΈΡ ΠΎΡ Π΅ΠΊΡΠΏΠ΅ΡΡΠΈ ΠΏΠΎ ΠΌΠ°ΡΠ΅ΠΌΠ°ΡΠΈΠΊΠ°:
WITH src AS (
SELECT unnest('{2,3,5,7,11,13,17,19}'::integer[]) prime
)
SELECT
exp(sum(ln(prime)))::integer val
FROM
src;
ΠΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΡΠ΅ generate_series Π²ΠΌΠ΅ΡΡΠΎ ΡΠΈΠΊΠ»ΠΈ
ΠΠ° ΠΊΠ°ΠΆΠ΅ΠΌ, ΡΠ΅ ΡΠΌΠ΅ ΠΈΠ·ΠΏΡΠ°Π²Π΅Π½ΠΈ ΠΏΡΠ΅Π΄ Π·Π°Π΄Π°ΡΠ°ΡΠ° Π΄Π° Π³Π΅Π½Π΅ΡΠΈΡΠ°ΠΌΠ΅ Π²ΡΠΈΡΠΊΠΈ Π²ΡΠ·ΠΌΠΎΠΆΠ½ΠΈ ΠΏΡΠ΅ΡΠΈΠΊΡΠΈ Π·Π° Π½ΠΈΠ· 'abcdefgh'
:
WITH RECURSIVE T AS (
SELECT 'abcdefgh' str
UNION ALL
SELECT
substr(str, 1, length(str) - 1)
FROM
T
WHERE
length(str) > 1
)
TABLE T;
Π‘ΠΈΠ³ΡΡΠ½ΠΈ Π»ΠΈ ΡΡΠ΅, ΡΠ΅ ΠΈΠΌΠ°ΡΠ΅ Π½ΡΠΆΠ΄Π° ΠΎΡ ΡΠ΅ΠΊΡΡΡΠΈΡ ΡΡΠΊ?.. ΠΠΊΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΡΠ΅ LATERAL
ΠΈ generate_series
, ΡΠΎΠ³Π°Π²Π° Π΄ΠΎΡΠΈ Π½ΡΠΌΠ° Π΄Π° ΠΈΠΌΠ°ΡΠ΅ Π½ΡΠΆΠ΄Π° ΠΎΡ CTE:
SELECT
substr(str, 1, ln) str
FROM
(VALUES('abcdefgh')) T(str)
, LATERAL(
SELECT generate_series(length(str), 1, -1) ln
) X;
ΠΡΠΎΠΌΠ΅Π½Π΅ΡΠ΅ ΡΡΡΡΠΊΡΡΡΠ°ΡΠ° Π½Π° Π±Π°Π·Π°ΡΠ° Π΄Π°Π½Π½ΠΈ
ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΈΠΌΠ°ΡΠ΅ ΡΠ°Π±Π»ΠΈΡΠ° ΡΡΡ ΡΡΠΎΠ±ΡΠ΅Π½ΠΈΡ Π²ΡΠ² ΡΠΎΡΡΠΌΠ° Ρ Π²ΡΡΠ·ΠΊΠΈ ΠΎΡ ΡΠΎΠ²Π° ΠΊΠΎΠΉ Π½Π° ΠΊΠΎΠ³ΠΎ Π΅ ΠΎΡΠ³ΠΎΠ²ΠΎΡΠΈΠ» ΠΈΠ»ΠΈ Π½ΠΈΡΠΊΠ°
CREATE TABLE message(
message_id
uuid
PRIMARY KEY
, reply_to
uuid
REFERENCES message
, body
text
);
CREATE INDEX ON message(reply_to);
Π, ΡΠΈΠΏΠΈΡΠ½Π° Π·Π°ΡΠ²ΠΊΠ° Π·Π° ΠΈΠ·ΡΠ΅Π³Π»ΡΠ½Π΅ Π½Π° Π²ΡΠΈΡΠΊΠΈ ΡΡΠΎΠ±ΡΠ΅Π½ΠΈΡ ΠΏΠΎ Π΅Π΄Π½Π° ΡΠ΅ΠΌΠ° ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π° ΡΠ°ΠΊΠ°:
WITH RECURSIVE T AS (
SELECT
*
FROM
message
WHERE
message_id = $1
UNION ALL
SELECT
m.*
FROM
T
JOIN
message m
ON m.reply_to = T.message_id
)
TABLE T;
ΠΠΎ ΡΡΠΉ ΠΊΠ°ΡΠΎ Π²ΠΈΠ½Π°Π³ΠΈ ΡΠ΅ Π½ΡΠΆΠ΄Π°Π΅ΠΌ ΠΎΡ ΡΡΠ»Π°ΡΠ° ΡΠ΅ΠΌΠ° ΠΎΡ ΠΎΡΠ½ΠΎΠ²Π½ΠΎΡΠΎ ΡΡΠΎΠ±ΡΠ΅Π½ΠΈΠ΅, ΡΠΎΠ³Π°Π²Π° Π·Π°ΡΠΎ Π½Π΅ Π½ΠΈ ΡΡΡΠ±Π²Π° Π΄ΠΎΠ±Π°Π²Π΅ΡΠ΅ Π½Π΅Π³ΠΎΠ²ΠΈΡ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ ΠΊΡΠΌ Π²ΡΠ΅ΠΊΠΈ Π·Π°ΠΏΠΈΡ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅Π½?
-- Π΄ΠΎΠ±Π°Π²ΠΈΠΌ ΠΏΠΎΠ»Π΅ Ρ ΠΎΠ±ΡΠΈΠΌ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΠΎΠΌ ΡΠ΅ΠΌΡ ΠΈ ΠΈΠ½Π΄Π΅ΠΊΡ Π½Π° Π½Π΅Π³ΠΎ
ALTER TABLE message
ADD COLUMN theme_id uuid;
CREATE INDEX ON message(theme_id);
-- ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·ΠΈΡΡΠ΅ΠΌ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ ΡΠ΅ΠΌΡ Π² ΡΡΠΈΠ³Π³Π΅ΡΠ΅ ΠΏΡΠΈ Π²ΡΡΠ°Π²ΠΊΠ΅
CREATE OR REPLACE FUNCTION ins() RETURNS TRIGGER AS $$
BEGIN
NEW.theme_id = CASE
WHEN NEW.reply_to IS NULL THEN NEW.message_id -- Π±Π΅ΡΠ΅ΠΌ ΠΈΠ· ΡΡΠ°ΡΡΠΎΠ²ΠΎΠ³ΠΎ ΡΠΎΠ±ΡΡΠΈΡ
ELSE ( -- ΠΈΠ»ΠΈ ΠΈΠ· ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ, Π½Π° ΠΊΠΎΡΠΎΡΠΎΠ΅ ΠΎΡΠ²Π΅ΡΠ°Π΅ΠΌ
SELECT
theme_id
FROM
message
WHERE
message_id = NEW.reply_to
)
END;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER ins BEFORE INSERT
ON message
FOR EACH ROW
EXECUTE PROCEDURE ins();
Π‘Π΅Π³Π° ΡΡΠ»Π°ΡΠ° Π½ΠΈ ΡΠ΅ΠΊΡΡΡΠΈΠ²Π½Π° Π·Π°ΡΠ²ΠΊΠ° ΠΌΠΎΠΆΠ΅ Π΄Π° Π±ΡΠ΄Π΅ Π½Π°ΠΌΠ°Π»Π΅Π½Π° ΡΠ°ΠΌΠΎ Π΄ΠΎ ΡΠΎΠ²Π°:
SELECT
*
FROM
message
WHERE
theme_id = $1;
ΠΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΡΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈ βΠΎΠ³ΡΠ°Π½ΠΈΡΠΈΡΠ΅Π»ΠΈβ
ΠΠΊΠΎ ΠΏΠΎ Π½ΡΠΊΠ°ΠΊΠ²Π° ΠΏΡΠΈΡΠΈΠ½Π° Π½Π΅ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΏΡΠΎΠΌΠ΅Π½ΠΈΠΌ ΡΡΡΡΠΊΡΡΡΠ°ΡΠ° Π½Π° Π±Π°Π·Π°ΡΠ° Π΄Π°Π½Π½ΠΈ, Π½Π΅ΠΊΠ° Π²ΠΈΠ΄ΠΈΠΌ Π½Π° ΠΊΠ°ΠΊΠ²ΠΎ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΡΠ°Π·ΡΠΈΡΠ°ΠΌΠ΅, ΡΠ°ΠΊΠ° ΡΠ΅ Π΄ΠΎΡΠΈ Π½Π°Π»ΠΈΡΠΈΠ΅ΡΠΎ Π½Π° Π³ΡΠ΅ΡΠΊΠ° Π² Π΄Π°Π½Π½ΠΈΡΠ΅ Π΄Π° Π½Π΅ Π²ΠΎΠ΄ΠΈ Π΄ΠΎ Π±Π΅Π·ΠΊΡΠ°ΠΉΠ½Π° ΡΠ΅ΠΊΡΡΡΠΈΡ.
ΠΡΠΎΡΡ Π½Π° Π΄ΡΠ»Π±ΠΎΡΠΈΠ½Π° Π½Π° ΡΠ΅ΠΊΡΡΡΠΈΡ
ΠΠΈΠ΅ ΠΏΡΠΎΡΡΠΎ ΡΠ²Π΅Π»ΠΈΡΠ°Π²Π°ΠΌΠ΅ Π±ΡΠΎΡΡΠ° Ρ Π΅Π΄ΠΈΠ½ΠΈΡΠ° Π½Π° Π²ΡΡΠΊΠ° ΡΡΡΠΏΠΊΠ° Π½Π° ΡΠ΅ΠΊΡΡΡΠΈΡ, Π΄ΠΎΠΊΠ°ΡΠΎ Π΄ΠΎΡΡΠΈΠ³Π½Π΅ΠΌ ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½ΠΈΠ΅, ΠΊΠΎΠ΅ΡΠΎ ΡΡΠΈΡΠ°ΠΌΠ΅ Π·Π° ΠΎΡΠ΅Π²ΠΈΠ΄Π½ΠΎ Π½Π΅Π°Π΄Π΅ΠΊΠ²Π°ΡΠ½ΠΎ:
WITH RECURSIVE T AS (
SELECT
0 i
...
UNION ALL
SELECT
i + 1
...
WHERE
T.i < 64 -- ΠΏΡΠ΅Π΄Π΅Π»
)
Pro: ΠΠΎΠ³Π°ΡΠΎ ΡΠ΅ ΠΎΠΏΠΈΡΠ°ΠΌΠ΅ Π΄Π° Π·Π°ΡΠΈΠΊΠ»ΠΈΠΌ, ΠΏΠ°ΠΊ Π½ΡΠΌΠ° Π΄Π° Π½Π°ΠΏΡΠ°Π²ΠΈΠΌ ΠΏΠΎΠ²Π΅ΡΠ΅ ΠΎΡ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΡ Π»ΠΈΠΌΠΈΡ ΠΎΡ ΠΈΡΠ΅ΡΠ°ΡΠΈΠΈ βΠ² Π΄ΡΠ»Π±ΠΎΡΠΈΠ½Π°β.
ΠΏΡΠΎΡΠΈΠ²: ΠΡΠΌΠ° Π³Π°ΡΠ°Π½ΡΠΈΡ, ΡΠ΅ Π½ΡΠΌΠ° Π΄Π° ΠΎΠ±ΡΠ°Π±ΠΎΡΠΈΠΌ ΠΎΡΠ½ΠΎΠ²ΠΎ ΡΡΡΠΈΡ Π·Π°ΠΏΠΈΡ - Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ Π½Π° Π΄ΡΠ»Π±ΠΎΡΠΈΠ½Π° 15 ΠΈ 25, Π° ΡΠ»Π΅Π΄ ΡΠΎΠ²Π° Π½Π° Π²ΡΠ΅ΠΊΠΈ +10. Π Π½ΠΈΠΊΠΎΠΉ Π½Π΅ ΠΎΠ±Π΅ΡΠ° Π½ΠΈΡΠΎ Π·Π° βΡΠΈΡΠΎΡΠΈΠ½Π°ΡΠ°β.
Π€ΠΎΡΠΌΠ°Π»Π½ΠΎ ΠΏΠΎΠ΄ΠΎΠ±Π½Π° ΡΠ΅ΠΊΡΡΡΠΈΡ Π½ΡΠΌΠ° Π΄Π° Π΅ Π±Π΅Π·ΠΊΡΠ°ΠΉΠ½Π°, Π½ΠΎ Π°ΠΊΠΎ Π½Π° Π²ΡΡΠΊΠ° ΡΡΡΠΏΠΊΠ° Π±ΡΠΎΡΡ Π½Π° Π·Π°ΠΏΠΈΡΠΈΡΠ΅ Π½Π°ΡΠ°ΡΡΠ²Π° Π΅ΠΊΡΠΏΠΎΠ½Π΅Π½ΡΠΈΠ°Π»Π½ΠΎ, Π²ΡΠΈΡΠΊΠΈ Π΄ΠΎΠ±ΡΠ΅ Π·Π½Π°Π΅ΠΌ ΠΊΠ°ΠΊ Π·Π°Π²ΡΡΡΠ²Π°...
ΠΠ°Π·ΠΈΡΠ΅Π» Π½Π° "ΠΏΡΡΠ΅ΠΊΠ°ΡΠ°"
ΠΠΎΠ±Π°Π²ΡΠΌΠ΅ Π°Π»ΡΠ΅ΡΠ½Π°ΡΠΈΠ²Π½ΠΎ Π²ΡΠΈΡΠΊΠΈ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΠΈ Π½Π° ΠΎΠ±Π΅ΠΊΡΠΈ, ΠΊΠΎΠΈΡΠΎ ΡΡΠ΅ΡΠ½Π°Ρ ΠΌΠ΅ ΠΏΠΎ ΠΏΡΡΡ Π½Π° ΡΠ΅ΠΊΡΡΡΠΈΡ Π² ΠΌΠ°ΡΠΈΠ², ΠΊΠΎΠΉΡΠΎ Π΅ ΡΠ½ΠΈΠΊΠ°Π»Π΅Π½ βΠΏΡΡβ ΠΊΡΠΌ Π½Π΅Π³ΠΎ:
WITH RECURSIVE T AS (
SELECT
ARRAY[id] path
...
UNION ALL
SELECT
path || id
...
WHERE
id <> ALL(T.path) -- Π½Π΅ ΡΠΎΠ²ΠΏΠ°Π΄Π°Π΅Ρ Π½ΠΈ Ρ ΠΎΠ΄Π½ΠΈΠΌ ΠΈΠ·
)
Pro: ΠΠΊΠΎ ΠΈΠΌΠ° ΡΠΈΠΊΡΠ» Π² Π΄Π°Π½Π½ΠΈΡΠ΅, Π½ΠΈΠ΅ Π°Π±ΡΠΎΠ»ΡΡΠ½ΠΎ Π½ΡΠΌΠ° Π΄Π° ΠΎΠ±ΡΠ°Π±ΠΎΡΠ²Π°ΠΌΠ΅ ΡΡΡΠΈΡ Π·Π°ΠΏΠΈΡ ΠΌΠ½ΠΎΠ³ΠΎΠΊΡΠ°ΡΠ½ΠΎ Π² ΡΠ°ΠΌΠΊΠΈΡΠ΅ Π½Π° Π΅Π΄ΠΈΠ½ ΠΈ ΡΡΡΠΈ ΠΏΡΡ.
ΠΏΡΠΎΡΠΈΠ²: ΠΠΎ Π² ΡΡΡΠΎΡΠΎ Π²ΡΠ΅ΠΌΠ΅ ΠΌΠΎΠΆΠ΅ΠΌ Π±ΡΠΊΠ²Π°Π»Π½ΠΎ Π΄Π° Π·Π°ΠΎΠ±ΠΈΠΊΠΎΠ»ΠΈΠΌ Π²ΡΠΈΡΠΊΠΈ Π·Π°ΠΏΠΈΡΠΈ, Π±Π΅Π· Π΄Π° ΡΠ΅ ΠΏΠΎΠ²ΡΠ°ΡΡΠΌΠ΅.
ΠΠ³ΡΠ°Π½ΠΈΡΠ΅Π½ΠΈΠ΅ Π½Π° Π΄ΡΠ»ΠΆΠΈΠ½Π°ΡΠ° Π½Π° ΠΏΡΡΡ
ΠΠ° Π΄Π° ΠΈΠ·Π±Π΅Π³Π½Π΅ΠΌ ΡΠΈΡΡΠ°ΡΠΈΡΡΠ° Π½Π° βΠ»ΡΡΠ°Π½Π΅β Π½Π° ΡΠ΅ΠΊΡΡΡΠΈΡ Π½Π° Π½Π΅ΡΠ°Π·Π±ΠΈΡΠ°Π΅ΠΌΠ° Π΄ΡΠ»Π±ΠΎΡΠΈΠ½Π°, ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΊΠΎΠΌΠ±ΠΈΠ½ΠΈΡΠ°ΠΌΠ΅ Π΄Π²Π°ΡΠ° ΠΏΡΠ΅Π΄ΠΈΡΠ½ΠΈ ΠΌΠ΅ΡΠΎΠ΄Π°. ΠΠ»ΠΈ, Π°ΠΊΠΎ Π½Π΅ ΠΈΡΠΊΠ°ΠΌΠ΅ Π΄Π° ΠΏΠΎΠ΄Π΄ΡΡΠΆΠ°ΠΌΠ΅ Π½Π΅Π½ΡΠΆΠ½ΠΈ ΠΏΠΎΠ»Π΅ΡΠ°, Π΄ΠΎΠΏΡΠ»Π½Π΅ΡΠ΅ ΡΡΠ»ΠΎΠ²ΠΈΠ΅ΡΠΎ Π·Π° ΠΏΡΠΎΠ΄ΡΠ»ΠΆΠ°Π²Π°Π½Π΅ Π½Π° ΡΠ΅ΠΊΡΡΡΠΈΡΡΠ° Ρ ΠΎΡΠ΅Π½ΠΊΠ° Π½Π° Π΄ΡΠ»ΠΆΠΈΠ½Π°ΡΠ° Π½Π° ΠΏΡΡΡ:
WITH RECURSIVE T AS (
SELECT
ARRAY[id] path
...
UNION ALL
SELECT
path || id
...
WHERE
id <> ALL(T.path) AND
array_length(T.path, 1) < 10
)
ΠΠ·Π±Π΅ΡΠ΅ΡΠ΅ ΠΌΠ΅ΡΠΎΠ΄ ΠΏΠΎ Π²Π°Ρ Π²ΠΊΡΡ!
ΠΠ·ΡΠΎΡΠ½ΠΈΠΊ: www.habr.com