рдЗрд╕ рд╕рдВрдмрдВрдз рдореЗрдВ DBMS рдЗрдиреНрд╣реАрдВ рд╕рд┐рджреНрдзрд╛рдВрддреЛрдВ рдкрд░ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИ - "рдЙрдиреНрд╣реЛрдВрдиреЗ рдореБрдЭрд╕реЗ рдЦреБрджрд╛рдИ рдХрд░рдиреЗ рдХреЛ рдХрд╣рд╛, рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ рдЦреБрджрд╛рдИ рдХреА"ред рдЖрдкрдХрд╛ рдЕрдиреБрд░реЛрдз рди рдХреЗрд╡рд▓ рдкрдбрд╝реЛрд╕реА рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рдзреАрдорд╛ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рд▓рдЧрд╛рддрд╛рд░ рдкреНрд░реЛрд╕реЗрд╕рд░ рд╕рдВрд╕рд╛рдзрди рд▓реЗ рд╕рдХрддрд╛ рд╣реИ, рдмрд▓реНрдХрд┐ рдкреВрд░реЗ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЛ "рдЫреЛрдбрд╝" рднреА рд╕рдХрддрд╛ рд╣реИ, рд╕рднреА рдЙрдкрд▓рдмреНрдз рдореЗрдореЛрд░реА рдХреЛ "рдЦрд╛" рд╕рдХрддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП рдЕрдирдВрдд рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХреЗ рд╡рд┐рд░реБрджреНрдз рд╕реБрд░рдХреНрд╖рд╛ - рдЬрд┐рдореНрдореЗрджрд╛рд░реА рд╕реНрд╡рдпрдВ рдбреЗрд╡рд▓рдкрд░ рдХреАред
PostgreSQL рдореЗрдВ, рдкреБрдирд░рд╛рд╡рд░реНрддреА рдкреНрд░рд╢реНрдиреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ WITH RECURSIVE
рдкреБрдирд░рд╛рд╡рд░реНрддреА рдкреНрд░рд╢реНрди рди рд▓рд┐рдЦреЗрдВ
рдФрд░ рдЧреИрд░-рдкреБрдирд░рд╛рд╡рд░реНрддреА рд▓рд┐рдЦреЗрдВред рднрд╡рджреАрдп, рдЖрдкрдХрд╛ рдХреЗ.рдУ.
рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, 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 -- ╨┐╤А╨╡╨┤╨╡╨╗
)
рдкреНрд░реЛ: рдЬрдм рд╣рдо рд▓реВрдк рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рддрдм рднреА рд╣рдо "рдЧрд╣рд░рд╛рдИ рдореЗрдВ" рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐рдпреЛрдВ рдХреА рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╕реАрдорд╛ рд╕реЗ рдЕрдзрд┐рдХ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗред
рд╡рд┐рдкрдХреНрд╖: рдЗрд╕ рдмрд╛рдд рдХреА рдХреЛрдИ рдЧрд╛рд░рдВрдЯреА рдирд╣реАрдВ рд╣реИ рдХрд┐ рд╣рдо рдЙрд╕реА рд░рд┐рдХреЙрд░реНрдб рдХреЛ рджреЛрдмрд╛рд░рд╛ рд╕рдВрд╕рд╛рдзрд┐рдд рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ - рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, 15 рдФрд░ 25 рдХреА рдЧрд╣рд░рд╛рдИ рдкрд░, рдФрд░ рдлрд┐рд░ рд╣рд░ +10 рдкрд░ред рдФрд░ рдХрд┐рд╕реА рдиреЗ рднреА "рдЪреМрдбрд╝рд╛рдИ" рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреБрдЫ рднреА рд╡рд╛рджрд╛ рдирд╣реАрдВ рдХрд┐рдпрд╛ред
рдФрдкрдЪрд╛рд░рд┐рдХ рд░реВрдк рд╕реЗ, рдРрд╕реА рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдЕрдирдВрдд рдирд╣реАрдВ рд╣реЛрдЧреА, рд▓реЗрдХрд┐рди рдпрджрд┐ рдкреНрд░рддреНрдпреЗрдХ рдЪрд░рдг рдкрд░ рд░рд┐рдХреЙрд░реНрдб рдХреА рд╕рдВрдЦреНрдпрд╛ рддреЗрдЬреА рд╕реЗ рдмрдврд╝рддреА рд╣реИ, рддреЛ рд╣рдо рд╕рднреА рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рд╕рдорд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ...
"рдкрде" рдХреЗ рд╕рдВрд░рдХреНрд╖рдХ
рд╣рдо рдмрд╛рд░реА-рдмрд╛рд░реА рд╕реЗ рд░рд┐рдХрд░реНрд╕рди рдкрде рдХреЗ рд╕рд╛рде рдЖрдП рд╕рднреА рдСрдмреНрдЬреЗрдХреНрдЯ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛рдУрдВ рдХреЛ рдПрдХ рд╕рд░рдгреА рдореЗрдВ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рдЬреЛ рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрджреНрд╡рд┐рддреАрдп "рдкрде" рд╣реИ:
WITH RECURSIVE T AS (
SELECT
ARRAY[id] path
...
UNION ALL
SELECT
path || id
...
WHERE
id <> ALL(T.path) -- ╨╜╨╡ ╤Б╨╛╨▓╨┐╨░╨┤╨░╨╡╤В ╨╜╨╕ ╤Б ╨╛╨┤╨╜╨╕╨╝ ╨╕╨╖
)
рдкреНрд░реЛ: рдпрджрд┐ рдбреЗрдЯрд╛ рдореЗрдВ рдХреЛрдИ рдЪрдХреНрд░ рд╣реИ, рддреЛ рд╣рдо рдПрдХ рд╣реА рд░рд┐рдХреЙрд░реНрдб рдХреЛ рдПрдХ рд╣реА рдкрде рдореЗрдВ рдмрд╛рд░-рдмрд╛рд░ рд╕рдВрд╕рд╛рдзрд┐рдд рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗред
рд╡рд┐рдкрдХреНрд╖: рд▓реЗрдХрд┐рди рд╕рд╛рде рд╣реА, рд╣рдо рдЦреБрдж рдХреЛ рджреЛрд╣рд░рд╛рдП рдмрд┐рдирд╛ рд╕рдЪрдореБрдЪ рд╕рднреА рд░рд┐рдХреЙрд░реНрдб рдХреЛ рдмрд╛рдпрдкрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдкрде рдХреА рд▓рдВрдмрд╛рдИ рд╕реАрдорд╛
рдЕрд╕рдВрдЧрдд рдЧрд╣рд░рд╛рдИ рдкрд░ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ "рднрдЯрдХрдиреЗ" рдХреА рд╕реНрдерд┐рддрд┐ рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдкрд┐рдЫрд▓реЗ рджреЛ рддрд░реАрдХреЛрдВ рдХреЛ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╛, рдпрджрд┐ рд╣рдо рдЕрдирд╛рд╡рд╢реНрдпрдХ рдлрд╝реАрд▓реНрдб рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдкрде рдХреА рд▓рдВрдмрд╛рдИ рдХреЗ рдЕрдиреБрдорд╛рди рдХреЗ рд╕рд╛рде рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдЬрд╛рд░реА рд░рдЦрдиреЗ рдХреА рд╢рд░реНрдд рдХреЛ рдкреВрд░рдХ рдХрд░реЗрдВ:
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