рдпрд╛ рд╕рдВрджрд░реНрднрд╛рдд рдбреАрдмреАрдПрдордПрд╕ рд╕рдорд╛рди рддрддреНрддреНрд╡рд╛рдВрд╡рд░ рдХрд╛рд░реНрдп рдХрд░рддреЗ - "рддреНрдпрд╛рдВрдиреА рдорд▓рд╛ рдЦреЛрджрд╛рдпрд▓рд╛ рд╕рд╛рдВрдЧрд┐рддрд▓реЗ, рдореНрд╣рдгреВрди рдореА рдЦреЛрджрд▓реЗ". рддреБрдордЪреА рд╡рд┐рдирдВрддреА рдХреЗрд╡рд│ рд╢реЗрдЬрд╛рд░реАрд▓ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдордВрдж рдХрд░реВ рд╢рдХрдд рдирд╛рд╣реА, рд╕рддрдд рдкреНрд░реЛрд╕реЗрд╕рд░ рд╕рдВрд╕рд╛рдзрдиреЗ рдШреЗрддрд╛рдд, рдкрд░рдВрддреБ рд╕рдВрдкреВрд░реНрдг рдбреЗрдЯрд╛рдмреЗрд╕ "рдбреНрд░реЙрдк" рдХрд░реВ рд╢рдХрддреЗ, рд╕рд░реНрд╡ рдЙрдкрд▓рдмреНрдз рдореЗрдорд░реА "рдЦрд╛рдд" рд╢рдХрддреЗ. рдЕрдирдВрдд рдкреБрдирд░рд╛рд╡реГрддреНрддреАрдкрд╛рд╕реВрди рд╕рдВрд░рдХреНрд╖рдг - рд╡рд┐рдХрд╛рд╕рдХрд╛рдЪреА рд╕реНрд╡рддрдГрдЪреА рдЬрдмрд╛рдмрджрд╛рд░реА.
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;
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;
рдкрд░рдВрддреБ рдЖрдкрд▓реНрдпрд╛рд▓рд╛ рдиреЗрд╣рдореА рдореВрд│ рд╕рдВрджреЗрд╢рд╛рддреВрди рд╕рдВрдкреВрд░реНрдг рд╡рд┐рд╖рдп рд╣рд╡рд╛ рдЕрд╕рддреЛ, рдордЧ рдЖрдкрдг рдХрд╛ рдирд╛рд╣реА рдкреНрд░рддреНрдпреЗрдХ рдПрдВрдЯреНрд░реАрдордзреНрдпреЗ рддреНрдпрд╛рдЪрд╛ рдЖрдпрдбреА рдЬреЛрдбрд╛ рд╕реНрд╡рдпрдВрдЪрд▓рд┐рдд?
-- ╨┤╨╛╨▒╨░╨▓╨╕╨╝ ╨┐╨╛╨╗╨╡ ╤Б ╨╛╨▒╤Й╨╕╨╝ ╨╕╨┤╨╡╨╜╤В╨╕╤Д╨╕╨║╨░╤В╨╛╤А╨╛╨╝ ╤В╨╡╨╝╤Л ╨╕ ╨╕╨╜╨┤╨╡╨║╤Б ╨╜╨░ ╨╜╨╡╨│╨╛
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