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;
ื ืืฆื generation_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;
ืึธืืขืจ ืืื ื ืืืจ ืฉืืขื ืืืง ืืึทืจืคึฟื ืื ืืื ืฆืข ืืขืืข ืคึฟืื ืืขืจ ืืืึธืจืฆื ืึธื ืืึธื, ืคืืจืืืืก ืืึธื ื ืื ืืืื ืืืื 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();
ืืืฆื ืืื ืืืขืจ ืืื ืฆืข ืจืขืงืืจืกืืืืข ืึธื ืคึฟืจืขื ืงืขื ืขื ืืืื ืจืืืืกื ืฆื ืคึผืื ืงื ืืขื:
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