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;

เจฒเฉ‚เจชเจธ เจฆเฉ€ เจฌเจœเจพเจ 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);

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;

เจชเจฐ เจ•เจฟเจ‰เจ‚เจ•เจฟ เจธเจพเจจเฉ‚เฉฐ เจนเจฎเฉ‡เจธเจผเจพ เจฐเฉ‚เจŸ เจธเฉฐเจฆเฉ‡เจธเจผ เจคเฉ‹เจ‚ เจชเฉ‚เจฐเฉ‡ เจตเจฟเจธเจผเฉ‡ เจฆเฉ€ เจฒเฉ‹เฉœ เจนเฉเฉฐเจฆเฉ€ เจนเฉˆ, เจซเจฟเจฐ เจ…เจธเฉ€เจ‚ เจ•เจฟเจ‰เจ‚ เจจเจนเฉ€เจ‚ เจ•เจฐเจฆเฉ‡ เจนเจฐ เจ‡เฉฐเจฆเจฐเจพเจœเจผ เจตเจฟเฉฑเจš เจ‡เจธเจฆเฉ€ 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();

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

เจ‡เฉฑเจ• เจŸเจฟเฉฑเจชเจฃเฉ€ เจœเฉ‹เฉœเฉ‹