á€ááá
á¹á
ááŸáá·áº áááºáááºá DBMS ááẠáá°áá®áá±á¬ á¡ááŒá±áá¶áá°áá»á¬ážáá±á«áºááœáẠáá¯ááºáá±á¬ááºááẠ- "áá°ážááá¯á·ááŒá±á¬áá±á¬á· áá°ážáááºá"á ááá·áºáá±á¬ááºážááá¯áá»ááºááẠá¡áááºáá®ážáá»ááºáž áá¯ááºáááºážá
ááºáá»á¬ážááᯠááŸá±ážááœá±ážá
á±áá¯á¶áá¬áá áááá¯áááºáá¬á¡áááºážá¡ááŒá
áºáá»á¬ážááᯠá¡áááºáááŒááºááá°áá±áá¯á¶áá¬áá áá±áá¬áá±á·á
áºáá
áºáá¯áá¯á¶ážááᯠ"áá»áá
áº" áá¬á áááŸáááá¯ááºáá±á¬ ááŸááºáá¬ááºá¡á¬ážáá¯á¶ážááᯠ"á
á¬ážááŒááºáž" ááá¯áááºáž áá¯ááºáá±á¬ááºááá¯ááºáááºá á¡áá¯á¶ážáááŸá ááŒááºááŸáá·áºááŒááºážá០áá¬ááœááºáá±ážááŒááºážá - ááŒá¯á
á¯áá°ááá¯ááºááá¯ááºááá¬áááºá
PostgreSQL ááœááºá ááá¯ááŸáá
áºááá·áº recursive queries áá»á¬ážááᯠá¡áá¯á¶ážááŒá¯ááá¯ááºáááºá WITH RECURSIVE
áááºáá¬áááºáᬠáá±ážááœááºážáá»á¬áž ááá±ážáá«ááŸáá·áº
áááºáá«ááá²áá² ááá¯ááºáá±á¬ á á¬áá»á¬ážááᯠáá±ážáá«á áá±ážá á¬ážá áœá¬ááŒáá·áº áááºá K.O.
ááááºáá±á¬á·á PostgreSQL ááẠáááºá¡áá¯á¶ážááŒá¯ááá¯ááºááá·áº áá¯ááºáá±á¬ááºááá¯ááºá áœááºážáá»á¬ážá áœá¬ááᯠáá±ážáá±á¬ááºáááºá ááá¯áẠrecursion ááá¯áá¯á¶ážáá«á
ááŒá¿áá¬á¡ááœáẠá¡ááŒá±áá¶á¡á¬ážááŒáá·áº ááœá²ááŒá¬ážáá±á¬áá»ááºážáááºáááºážááᯠá¡áá¯á¶ážááŒá¯áá«á
ááá«ááá¶ááŸá¬ ááŒá¿áá¬ááᯠâááá°áá®áá±á¬áááºâ á០ááŒáá·áºááá¯ááºáááºá áá±á¬ááºážáá«ážááŸá¬ áá®ááá¯á¡ááŒá±á¡áá±áá»áá¯áž á¥ááá¬áá±ážáá²á·áááºá
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;
loops áá»á¬ážá¡á á¬áž 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;
ááá¯á·áá±á¬áº áá»áœááºá¯ááºááá¯á·ááẠroot message á០áá±á«ááºážá ááºáá áºáá¯áá¯á¶ážááᯠá¡ááŒá²áááºážááá¯á¡ááºáá±áá±á¬ááŒá±á¬áá·áºá áá»áœááºá¯ááºááá¯á·ááẠá¡áááºááŒá±á¬áá·áºááá¯ááºáá±á¬ááºááŒááááºážá ááá·áºááœááºážááŸá¯áá áºáá¯á á®ááœáẠáááºážá ID ááá¯ááá·áºáá«á á¡ááá¯á¡áá»á±á¬ááº?
-- ЎПбавОЌ пПле Ñ ÐŸÐ±ÑОЌ ОЎеМÑОÑОкаÑПÑПЌ ÑÐµÐŒÑ Ðž ÐžÐœÐŽÐµÐºÑ ÐœÐ° МегП
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();
ááá¯áá»áœááºá¯ááºááá¯á·á recursive query áá
áºáá¯áá¯á¶ážááᯠá€áá»áŸá¡áá áá»áŸá±á¬á·áá»ááá¯ááºáááº-
SELECT
*
FROM
message
WHERE
theme_id = $1;
á¡áá¯á¶ážááŒá¯áá¬ážáá±á¬ "ááá·áºáááºáá»ááºáá»á¬áž" ááá¯áá¯á¶ážáá«
á¡ááŒá±á¬ááºážáá áºáá¯áá¯ááŒá±á¬áá·áº áá±áá¬áá±á·á áºá ááœá²á·á ááºážáá¯á¶ááᯠáá»áœááºá¯ááºááá¯á· áááŒá±á¬ááºážáá²ááá¯ááºáá«áá áá±áá¬ááœáẠá¡ááŸá¬ážá¡ááœááºážáá áºáá¯ááŸááá±ááŒááºážáááºááẠá¡áá¯á¶ážáá²á·ááŒááºááŸáá·áºááŒááºážááá¯á·áááœá¬ážááá¯ááºá á±ááẠáá»áœááºá¯ááºááá¯á·á¡á¬ážááá¯ážááá¯ááºáá±á¬á¡áá¬ááᯠááŒáá·áºááŒáá«á áá¯á·á
Recursion depth áááºááŒááº
áá»áœááºá¯ááºááá¯á·ááẠááá¯á¶áá±á¬ááºáᯠáá»áœááºá¯ááºááá¯á·áá°ááá±á¬ ááá·áºáááºáá»ááºááá¯á·áá±á¬ááºááŸááááºá¡áá áá»áœááºá¯ááºááá¯á·ááẠááŒááºááŸáá·áºááŒááºážá¡ááá·áºáá áºáá¯á á®ááœáẠáá±á¬ááºáá¬áá áºáá¯á á®ááᯠáá áºáá¯ááŒá®ážáá áºáᯠááá¯ážáá±ážáááº-
WITH RECURSIVE T AS (
SELECT
0 i
...
UNION ALL
SELECT
i + 1
...
WHERE
T.i < 64 -- пÑеЎел
)
Pro ááá¯: áá»áœááºá¯ááºááá¯á·ááẠááŸáá·áºáááºáááºááŒáá¯ážá
á¬ážáá±á¬á¡áá«á áá»áœááºá¯ááºááá¯á·ááẠáááºááŸááºáá¬ážáá±á¬ ááá·áºáááºáá»ááºááẠáááá¯á
á±áá² âáááºááŸáá¯ááºážá
áœá¬â áááºááŒááºážááŒá¯áá«áááºá
Cons: áá°áá®áá±á¬ááŸááºáááºážááᯠáá»áœááºá¯ááºááá¯á· áááºáá¶áá¯ááºáá±á¬ááºáááºááá¯ááºááŒá±á¬ááºáž á¡á¬ááá¶áá»ááºáááŸááá«á á¥ááá¬á á¡ááẠ15 ááŸáá·áº 25 á ááá¯á·áá±á¬áẠ+10 ááá¯ááºážá âá¡áá¶â ááŸáá·áº áááºáááºá áááºáá°áá»áŸ áááááá±ážáá²á·ááŒáá«á
ááá¬ážáááºá¡á¬ážááŒáá·áºá ááá¯ááá¯á·áá±á¬ááŒááºááŸáá·áºááŒááºážááẠá¡ááá·áºá¡áááºáááŸáááá¯ááºáá±á¬áºáááºáž á¡ááá·áºáá áºááá·áºáá»ááºážá á®ááœáẠááŸááºáááºážá¡áá±á¡ááœááºáá»á¬áž á¡áááá¯ážáá¬áá«áá áááºážááẠáááºááá¯á·á¡áá¯á¶ážáááºáááºááᯠáá»áœááºá¯ááºááá¯á·á¡á¬ážáá¯á¶áž áá±á¬ááºážá áœá¬áááá«áááºá
"áááºážá ááº" ááá¯á¡á¯ááºááááºážáá°
áá»áœááºá¯ááºááá¯á·ááẠááŒááºáááºáá¯áá¯á¶ážáááºážááŒá±á¬ááºážáá áºáá»áŸá±á¬ááºááœáẠáá»áœááºá¯ááºááá¯á·ááŒá¯á¶ááœá±á·áá²á·áááá·áº á¡áá¬ááá¹áᯠááœá²ááŒá¬ážáááºááŸááºááŸá¯á¡á¬ážáá¯á¶ážááᯠá¡áááºážá¡áá»ááºážáá áºáá¯áá²ááá¯á· á¡ááŸáá·áºá¡ááŒá±á¬ááºážááŒá áºááŒá®ážá áááºážá¡ááœáẠáá°ážááŒá¬ážáá±á¬ âáááºážááŒá±á¬ááºážâ ááŒá áºááá·áºá
WITH RECURSIVE T AS (
SELECT
ARRAY[id] path
...
UNION ALL
SELECT
path || id
...
WHERE
id <> ALL(T.path) -- Ме ÑÐŸÐ²Ð¿Ð°ÐŽÐ°ÐµÑ ÐœÐž Ñ ÐŸÐŽÐœÐžÐŒ Оз
)
Pro ááá¯: áá±áá¬áá²ááœáẠá
ááºááá¯ááºážáá
áºáá¯ááŸááá±áá«áá áá°áá®áá±á¬áááºážááŒá±á¬ááºážáá
áºáá¯áááºážááœáẠáááºáá«ááá²áá² áá¯ááºáá±á¬ááºáááºááá¯ááºáá«á
Cons: áá«áá±ááá·áº áá
áºáá»áááºáááºážááŸá¬áááºá áá»áœááºá¯ááºááá¯á·ááẠááááááá¯ááºááᯠáááºáá«ááá²áá²ááá¯ááºáá² ááŸááºáááºážá¡á¬ážáá¯á¶ážááᯠá
á¬áá¬ážá¡ááá¯ááºáž áá»á±á¬áºááŒááºááá¯ááºáááºá
áááºážááŒá±á¬ááºáž á¡ááŸáẠááá·áºáááºáá»ááº
áá¬ážááááºááá¯ááºáá±á¬ á¡áááºááŸáá¯ááºážááœáẠáááºáá«ááá²áá² ááŸáá·áºáááºááŒááºážáá¡ááŒá±á¡áá±ááᯠááŸá±á¬ááºááŸá¬ážáááºá áá»áœááºá¯ááºááá¯á·ááẠááááºáááºážáááºážááŸá áºáá¯ááᯠáá±á«ááºážá ááºááá¯ááºáááºá ááá¯á·ááá¯áẠáááá¯á¡ááºáá±á¬á¡ááœááºáá»á¬ážááᯠáá»áœááºá¯ááºááá¯á· ááá¶á·ááá¯ážááá¯áá«áá áááºážááŒá±á¬ááºážá¡ááŸáẠááá·áºááŸááºážáá»ááºááŒáá·áº áááºáá«ááá²áá² áááºáááºáá¯ááºáá±á¬ááºááẠá¡ááŒá±á¡áá±á¡á¬áž ááŒáá·áºá áœááºáá«-
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
)
ááá·áºá¡ááá¬á¡ááœáẠáááºážáááºážááᯠááœá±ážáá»ááºáá«á
source: www.habr.com