PostgreSQL เด†เดจเตเดฑเดฟเดชเดพเดฑเตเดฑเต‡เดฃเตเด•เตพ: "เด…เดจเดจเตเดคเดค เด’เดฐเต เดชเดฐเดฟเดงเดฟเดฏเดฒเตเดฒ!", เด…เดฒเตเดฒเต†เด™เตเด•เดฟเตฝ เด†เดตเตผเดคเตเดคเดจเดคเตเดคเต†เด•เตเด•เตเดฑเดฟเดšเตเดšเต เด…เตฝเดชเตเดชเด‚

เด†เดตเตผเดคเตเดคเดจเด‚ - เดฌเดจเตเดงเดชเตเดชเต†เดŸเตเดŸ เดกเดพเดฑเตเดฑเดฏเดฟเตฝ เด’เดฐเต‡ "เด†เดดเดคเตเดคเดฟเดฒเตเดณเตเดณ" เดชเตเดฐเดตเตผเดคเตเดคเดจเด™เตเด™เตพ เดจเดŸเดคเตเดคเตเด•เดฏเดพเดฃเต†เด™เตเด•เดฟเตฝ เดตเดณเดฐเต† เดถเด•เตเดคเดตเตเด‚ เดธเต—เด•เดฐเตเดฏเดชเตเดฐเดฆเดตเตเดฎเดพเดฏ เด’เดฐเต เดธเด‚เดตเดฟเดงเดพเดจเด‚. เดŽเดจเตเดจเดพเตฝ เด…เดจเดฟเดฏเดจเตเดคเตเดฐเดฟเดคเดฎเดพเดฏ เด†เดตเตผเดคเตเดคเดจเด‚ เด’เดฐเต เดคเดฟเดจเตเดฎเดฏเดพเดฃเต, เด…เดคเต เด’เดจเตเดจเดฟเดฒเต‡เด•เตเด•เต เดจเดฏเดฟเดšเตเดšเต‡เด•เตเด•เดพเด‚ เด…เดจเดจเตเดคเดฎเดพเดฏ เดตเดงเดถเดฟเด•เตเดท เดชเตเดฐเต‹เดธเดธเตเดธเต, เด…เดฒเตเดฒเต†เด™เตเด•เดฟเตฝ (เด•เต‚เดŸเตเดคเตฝ เดธเด‚เดญเดตเดฟเด•เตเด•เตเดจเตเดจเดคเต). เดฒเดญเตเดฏเดฎเดพเดฏ เดŽเดฒเตเดฒเดพ เดฎเต†เดฎเตเดฎเดฑเดฟเดฏเตเด‚ "เด•เดดเดฟเด•เตเด•เตเดจเตเดจเต".

PostgreSQL เด†เดจเตเดฑเดฟเดชเดพเดฑเตเดฑเต‡เดฃเตเด•เตพ: "เด…เดจเดจเตเดคเดค เด’เดฐเต เดชเดฐเดฟเดงเดฟเดฏเดฒเตเดฒ!", เด…เดฒเตเดฒเต†เด™เตเด•เดฟเตฝ เด†เดตเตผเดคเตเดคเดจเดคเตเดคเต†เด•เตเด•เตเดฑเดฟเดšเตเดšเต เด…เตฝเดชเตเดชเด‚
เด‡เด•เตเด•เดพเดฐเตเดฏเดคเตเดคเดฟเตฝ เดกเดฟเดฌเดฟเดŽเด‚เดŽเดธเต เด’เดฐเต‡ เดคเดคเตเดคเตเดตเด™เตเด™เดณเดฟเตฝ เดชเตเดฐเดตเตผเดคเตเดคเดฟเด•เตเด•เตเดจเตเดจเต - "เด…เดตเตผ เดŽเดจเตเดจเต‹เดŸเต เด•เตเดดเดฟเด•เตเด•เดพเตป เดชเดฑเดžเตเดžเต, เด…เดคเดฟเดจเดพเตฝ เดžเดพเตป เด•เตเดดเดฟเด•เตเด•เตเดจเตเดจเต". เดจเดฟเด™เตเด™เดณเตเดŸเต† เด…เดญเตเดฏเตผเดคเตเดฅเดจ เด…เดฏเตฝ เดชเตเดฐเด•เตเดฐเดฟเดฏเด•เดณเต† เดฎเดจเตเดฆเด—เดคเดฟเดฏเดฟเดฒเดพเด•เตเด•เดพเตป เดฎเดพเดคเตเดฐเดฎเดฒเตเดฒ, เดชเตเดฐเต‹เดธเดธเตผ เด‰เดฑเดตเดฟเดŸเด™เตเด™เตพ เดจเดฟเดฐเดจเตเดคเดฐเด‚ เดเดฑเตเดฑเต†เดŸเตเด•เตเด•เดพเดจเตเด‚ เดฎเดพเดคเตเดฐเดฎเดฒเตเดฒ, เดฎเตเดดเตเดตเตป เดกเดพเดฑเตเดฑเดพเดฌเต‡เดธเตเด‚ "เดกเตเดฐเต‹เดชเตเดชเต" เดšเต†เดฏเตเดฏเดพเดจเตเด‚, เดฒเดญเตเดฏเดฎเดพเดฏ เดŽเดฒเตเดฒเดพ เดฎเต†เดฎเตเดฎเดฑเดฟเดฏเตเด‚ "เดคเดฟเดจเตเดจเดพเดจเตเด‚" เด•เดดเดฟเดฏเตเด‚. เด…เดจเดจเตเดคเดฎเดพเดฏ เด†เดตเตผเดคเตเดคเดจเดคเตเดคเดฟเดจเต†เดคเดฟเดฐเดพเดฏ เดธเด‚เดฐเด•เตเดทเดฃเด‚ - เดกเดตเดฒเดชเตเดชเดฑเตเดŸเต† เดคเดจเตเดจเต† เด‰เดคเตเดคเดฐเดตเดพเดฆเดฟเดคเตเดคเด‚.

PostgreSQL-เตฝ, เดตเดดเดฟ เด†เดตเตผเดคเตเดคเดจ เดšเต‹เดฆเตเดฏเด™เตเด™เตพ เด‰เดชเดฏเต‹เด—เดฟเด•เตเด•เดพเดจเตเดณเตเดณ เด•เดดเดฟเดตเต WITH RECURSIVE เดชเดคเดฟเดชเตเดชเต 8.4-เดจเตเดฑเต† เด•เดพเดฒเดคเตเดคเดพเดฃเต เดชเตเดฐเดคเตเดฏเด•เตเดทเดชเตเดชเต†เดŸเตเดŸเดคเต, เดชเด•เตเดทเต‡ เดจเดฟเด™เตเด™เตพเด•เตเด•เต เดคเตเดŸเตผเดจเตเดจเตเด‚ เดฆเตเตผเดฌเดฒเดฎเดพเดฏ "เดชเตเดฐเดคเดฟเดฐเต‹เดงเดฐเดนเดฟเดค" เด…เดญเตเดฏเตผเดคเตเดฅเดจเด•เตพ เดชเดคเดฟเดตเดพเดฏเดฟ เดจเต‡เดฐเดฟเดŸเดพเด‚. เด‡เดคเตเดคเดฐเดคเตเดคเดฟเดฒเตเดณเตเดณ เดชเตเดฐเดถเตเดจเด™เตเด™เดณเดฟเตฝ เดจเดฟเดจเตเดจเต เดธเตเดตเดฏเด‚ เดŽเด™เตเด™เดจเต† เดฐเด•เตเดทเดชเตเดชเต†เดŸเดพเด‚?

เด†เดตเตผเดคเตเดคเดจ เดšเต‹เดฆเตเดฏเด™เตเด™เตพ เดŽเดดเตเดคเดฐเตเดคเต

เด•เต‚เดŸเดพเดคเต† เด†เดตเตผเดคเตเดคเดจเดฎเดฟเดฒเตเดฒเดพเดคเตเดคเดต เดŽเดดเตเดคเตเด•. เด†เดคเตเดฎเดพเตผเดคเตเดฅเดคเดฏเต‹เดŸเต†, เดจเดฟเด™เตเด™เดณเตเดŸเต† เด•เต†.เด’.

เดตเดพเดธเตเดคเดตเดคเตเดคเดฟเตฝ, PostgreSQL เดจเดฟเด™เตเด™เตพเด•เตเด•เต เด‰เดชเดฏเต‹เด—เดฟเด•เตเด•เดพเดจเดพเด•เตเดจเตเดจ เดงเดพเดฐเดพเดณเด‚ เดชเตเดฐเดตเตผเดคเตเดคเดจเด™เตเด™เตพ เดจเตฝเด•เตเดจเตเดจเต เด…เดฒเตเดฒ เด†เดตเตผเดคเตเดคเดจเด‚ เดชเตเดฐเดฏเต‹เด—เดฟเด•เตเด•เตเด•.

เดชเตเดฐเดถเตเดจเดคเตเดคเดฟเดจเต เด…เดŸเดฟเดธเตเดฅเดพเดจเดชเดฐเดฎเดพเดฏเดฟ เดตเตเดฏเดคเตเดฏเดธเตเดคเดฎเดพเดฏ เดธเดฎเต€เดชเดจเด‚ เด‰เดชเดฏเต‹เด—เดฟเด•เตเด•เตเด•

เดšเดฟเดฒเดชเตเดชเต‹เตพ เดจเดฟเด™เตเด™เตพเด•เตเด•เต "เดตเตเดฏเดคเตเดฏเดธเตเดค เดตเดถเดคเตเดคเต" เดจเดฟเดจเตเดจเต เดชเตเดฐเดถเตเดจเด‚ เดจเต‹เด•เตเด•เดพเด‚. เด…เดคเตเดคเดฐเดฎเตŠเดฐเต เดธเดพเดนเดšเดฐเตเดฏเดคเตเดคเดฟเดจเตเดฑเต† เด’เดฐเต เด‰เดฆเดพเดนเดฐเดฃเด‚ เดžเดพเตป เดฒเต‡เด–เดจเดคเตเดคเดฟเตฝ เดจเตฝเด•เดฟ "SQL HowTo: 1000 เด‰เด‚ เดเด•เต€เด•เดฐเดฃเดคเตเดคเดฟเดจเตเดฑเต† เด’เดฐเต เดตเดดเดฟเดฏเตเด‚" - เด‡เดทเตโ€ŒเดŸเดพเดจเตเดธเตƒเดค เด…เด—เตเดฐเด—เต‡เดฑเตเดฑเต เดซเด‚เด—เตโ€Œเดทเดจเตเด•เตพ เด‰เดชเดฏเต‹เด—เดฟเด•เตเด•เดพเดคเต† เด’เดฐเต เด•เต‚เดŸเตเดŸเด‚ เดธเด‚เด–เตเดฏเด•เดณเตเดŸเต† เด—เตเดฃเดจเด‚:

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;

เดฒเต‚เดชเตเดชเตเด•เตพเด•เตเด•เต เดชเด•เดฐเด‚ เดœเดจเดฑเต‡เดฑเตเดฑเต_เดธเต€เดฐเต€เดธเต เด‰เดชเดฏเต‹เด—เดฟเด•เตเด•เตเด•

เด’เดฐเต เดธเตโ€ŒเดŸเตเดฐเดฟเด™เตเด™เดฟเดจเต เดธเดพเดงเตเดฏเดฎเดพเดฏ เดŽเดฒเตเดฒเดพ เดชเตเดฐเดฟเดซเดฟเด•เตโ€Œเดธเตเด•เดณเตเด‚ เดธเตƒเดทเตโ€ŒเดŸเดฟเด•เตเด•เดพเดจเตเดณเตเดณ เดšเตเดฎเดคเดฒเดฏเดพเดฃเต เดžเด™เตเด™เตพ เดจเต‡เดฐเดฟเดŸเตเดจเตเดจเดคเต†เดจเตเดจเต เดชเดฑเดฏเดพเด‚ '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);

PostgreSQL เด†เดจเตเดฑเดฟเดชเดพเดฑเตเดฑเต‡เดฃเตเด•เตพ: "เด…เดจเดจเตเดคเดค เด’เดฐเต เดชเดฐเดฟเดงเดฟเดฏเดฒเตเดฒ!", เด…เดฒเตเดฒเต†เด™เตเด•เดฟเตฝ เด†เดตเตผเดคเตเดคเดจเดคเตเดคเต†เด•เตเด•เตเดฑเดฟเดšเตเดšเต เด…เตฝเดชเตเดชเด‚
เดถเดฐเดฟ, เด’เดฐเต เดตเดฟเดทเดฏเดคเตเดคเดฟเตฝ เดŽเดฒเตเดฒเดพ เดธเดจเตเดฆเต‡เดถเด™เตเด™เดณเตเด‚ เดกเต—เตบเดฒเต‹เดกเต เดšเต†เดฏเตเดฏเตเดจเตเดจเดคเดฟเดจเตเดณเตเดณ เด’เดฐเต เดธเดพเดงเดพเดฐเดฃ เด…เดญเตเดฏเตผเดคเตเดฅเดจ เด‡เดคเตเดชเต‹เดฒเต†เดฏเดพเดฃเต:

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();

PostgreSQL เด†เดจเตเดฑเดฟเดชเดพเดฑเตเดฑเต‡เดฃเตเด•เตพ: "เด…เดจเดจเตเดคเดค เด’เดฐเต เดชเดฐเดฟเดงเดฟเดฏเดฒเตเดฒ!", เด…เดฒเตเดฒเต†เด™เตเด•เดฟเตฝ เด†เดตเตผเดคเตเดคเดจเดคเตเดคเต†เด•เตเด•เตเดฑเดฟเดšเตเดšเต เด…เตฝเดชเตเดชเด‚
เด‡เดชเตเดชเต‹เตพ เดžเด™เตเด™เดณเตเดŸเต† เดฎเตเดดเตเดตเตป เด†เดตเตผเดคเตเดคเดจ เด…เดจเตเดตเต‡เดทเดฃเดตเตเด‚ เด‡เดคเดฟเดฒเต‡เด•เตเด•เต เดšเตเดฐเตเด•เตเด•เดพเด‚:

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 เดฒเตเด‚. "เดตเดฟเดถเดพเดฒเดค"เดฏเต†เด•เตเด•เตเดฑเดฟเดšเตเดšเต เด†เดฐเตเด‚ เด’เดจเตเดจเตเด‚ เดตเดพเด—เตเดฆเดพเดจเด‚ เดšเต†เดฏเตเดคเดฟเดฒเตเดฒ.

เด”เดชเดšเดพเดฐเดฟเด•เดฎเดพเดฏเดฟ, เด…เดคเตเดคเดฐเดฎเตŠเดฐเต เด†เดตเตผเดคเตเดคเดจเด‚ เด…เดจเดจเตเดคเดฎเดพเดฏเดฟเดฐเดฟเด•เตเด•เดฟเดฒเตเดฒ, เดŽเดจเตเดจเดพเตฝ เด“เดฐเต‹ เด˜เดŸเตเดŸเดคเตเดคเดฟเดฒเตเด‚ เดฑเต†เด•เตเด•เต‹เตผเดกเตเด•เดณเตเดŸเต† เดŽเดฃเตเดฃเด‚ เด•เตเดฐเดฎเดพเดคเต€เดคเดฎเดพเดฏเดฟ เดตเตผเดฆเตเดงเดฟเด•เตเด•เตเด•เดฏเดพเดฃเต†เด™เตเด•เดฟเตฝ, เด…เดคเต เดŽเด™เตเด™เดจเต† เด…เดตเดธเดพเดจเดฟเด•เตเด•เตเดฎเต†เดจเตเดจเต เดจเดฎเตเด•เตเด•เต†เดฒเตเดฒเดพเดตเตผเด•เตเด•เตเด‚ เดจเดจเตเดจเดพเดฏเดฟ เด…เดฑเดฟเดฏเดพเด‚...

PostgreSQL เด†เดจเตเดฑเดฟเดชเดพเดฑเตเดฑเต‡เดฃเตเด•เตพ: "เด…เดจเดจเตเดคเดค เด’เดฐเต เดชเดฐเดฟเดงเดฟเดฏเดฒเตเดฒ!", เด…เดฒเตเดฒเต†เด™เตเด•เดฟเตฝ เด†เดตเตผเดคเตเดคเดจเดคเตเดคเต†เด•เตเด•เตเดฑเดฟเดšเตเดšเต เด…เตฝเดชเตเดชเด‚"เดšเต†เดธเตเดธเตเดฌเต‹เตผเดกเดฟเดฒเต† เดงเดพเดจเตเดฏเด™เตเด™เดณเตเดŸเต† เดชเตเดฐเดถเตเดจเด‚" เด•เดพเดฃเตเด•

"เดชเดพเดค"เดฏเตเดŸเต† เด•เดพเดตเตฝเด•เตเด•เดพเดฐเตป

เด†เดตเตผเดคเตเดคเดจ เดชเดพเดคเดฏเดฟเตฝ เดžเด™เตเด™เตพ เดจเต‡เดฐเดฟเดŸเตเดŸ เดŽเดฒเตเดฒเดพ เด’เดฌเตโ€Œเดœเด•เตโ€Œเดฑเตเดฑเต เดเดกเดจเตเดฑเดฟเดซเดฏเดฑเตเด•เดณเตเด‚ เด’เดฐเต เด…เดฑเต‡เดฏเดฟเดฒเต‡เด•เตเด•เต เด’เดจเตเดจเดฟเดŸเดตเดฟเดŸเตเดŸเต เดšเต‡เตผเด•เตเด•เตเดจเตเดจเต, เด…เดคเตŠเดฐเต เดธเดตเดฟเดถเต‡เดทเดฎเดพเดฏ "เดชเดพเดคเตเดคเต" เด†เดฃเต:

WITH RECURSIVE T AS (
  SELECT
    ARRAY[id] path
  ...
UNION ALL
  SELECT
    path || id
  ...
  WHERE
    id <> ALL(T.path) -- ะฝะต ัะพะฒะฟะฐะดะฐะตั‚ ะฝะธ ั ะพะดะฝะธะผ ะธะท
)

เดชเตเดฐเต‹: เดกเดพเดฑเตเดฑเดฏเดฟเตฝ เด’เดฐเต เดธเตˆเด•เตเด•เดฟเตพ เด‰เดฃเตเดŸเต†เด™เตเด•เดฟเตฝ, เด’เดฐเต‡ เดชเดพเดคเดฏเดฟเตฝ เดžเด™เตเด™เตพ เด’เดฐเต‡ เดฑเต†เด•เตเด•เต‹เตผเดกเต เด†เดตเตผเดคเตเดคเดฟเดšเตเดšเต เดชเตเดฐเต‹เดธเดธเตเดธเต เดšเต†เดฏเตเดฏเดฟเดฒเตเดฒ.
เดฌเดพเด•เตเด•เตเดŸเตเดฐเต†เดฏเดฟเดธเตเด•เต†เดพเดฃเตเดŸเตเต: เดŽเดจเตเดจเดพเตฝ เด…เดคเต‡ เดธเดฎเดฏเด‚, เดจเดฎเตเด•เตเด•เต เดธเตเดตเดฏเด‚ เด†เดตเตผเดคเตเดคเดฟเด•เตเด•เดพเดคเต† เดŽเดฒเตเดฒเดพ เดฑเต†เด•เตเด•เต‹เตผเดกเตเด•เดณเตเด‚ เด…เด•เตเดทเดฐเดพเตผเดคเตเดฅเดคเตเดคเดฟเตฝ เดฎเดฑเดฟเด•เดŸเด•เตเด•เดพเตป เด•เดดเดฟเดฏเตเด‚.

PostgreSQL เด†เดจเตเดฑเดฟเดชเดพเดฑเตเดฑเต‡เดฃเตเด•เตพ: "เด…เดจเดจเตเดคเดค เด’เดฐเต เดชเดฐเดฟเดงเดฟเดฏเดฒเตเดฒ!", เด…เดฒเตเดฒเต†เด™เตเด•เดฟเตฝ เด†เดตเตผเดคเตเดคเดจเดคเตเดคเต†เด•เตเด•เตเดฑเดฟเดšเตเดšเต เด…เตฝเดชเตเดชเด‚"เดจเตˆเดฑเตเดฑเดฟเดจเตเดฑเต† เดจเต€เด•เตเด•เดคเตเดคเดฟเดจเตเดฑเต† เดชเตเดฐเดถเตเดจเด‚" เด•เดพเดฃเตเด•

เดชเดพเดค เดฆเตˆเตผเด˜เตเดฏ เดชเดฐเดฟเดงเดฟ

เดฎเดจเดธเตเดธเดฟเดฒเดพเด•เตเด•เดพเตป เด•เดดเดฟเดฏเดพเดคเตเดค เด†เดดเดคเตเดคเดฟเตฝ "เด…เดฒเดžเตเดžเตเดชเต‹เด•เตเดจเตเดจ" เด†เดตเตผเดคเตเดคเดจเดคเตเดคเดฟเดจเตเดฑเต† เดธเดพเดนเดšเดฐเตเดฏเด‚ เด’เดดเดฟเดตเดพเด•เตเด•เดพเตป, เดจเดฎเตเด•เตเด•เต เดฎเตเดฎเตเดชเดคเตเดคเต† เดฐเดฃเตเดŸเต เดฐเต€เดคเดฟเด•เตพ เดธเด‚เดฏเต‹เดœเดฟเดชเตเดชเดฟเด•เตเด•เดพเด‚. เด…เดฒเตเดฒเต†เด™เตเด•เดฟเตฝ, เด…เดจเดพเดตเดถเตเดฏเดฎเดพเดฏ เดซเต€เตฝเดกเตเด•เตพ เดชเดฟเดจเตเดคเตเดฃเดฏเตเด•เตเด•เดพเตป เดžเด™เตเด™เตพ เด†เด—เตเดฐเดนเดฟเด•เตเด•เตเดจเตเดจเดฟเดฒเตเดฒเต†เด™เตเด•เดฟเตฝ, เดชเดพเดคเดฏเตเดŸเต† เดฆเตˆเตผเด˜เตเดฏเดคเตเดคเดฟเดจเตเดฑเต† เด’เดฐเต เดŽเดธเตเดฑเตเดฑเดฟเดฎเต‡เดฑเตเดฑเต เด‰เดชเดฏเต‹เด—เดฟเดšเตเดšเต เด†เดตเตผเดคเตเดคเดจเด‚ เดคเตเดŸเดฐเตเดจเตเดจเดคเดฟเดจเตเดณเตเดณ เดตเตเดฏเดตเดธเตเดฅเดฏเตเด•เตเด•เต เด…เดจเตเดฌเดจเตเดงเดฎเดพเดฏเดฟ เดจเตฝเด•เตเด•:

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

เด’เดฐเต เด…เดญเดฟเดชเตเดฐเดพเดฏเด‚ เดšเต‡เตผเด•เตเด•เตเด•