PostgreSQL Antipatterns: "ื•ืžืขื ื“ื™ืงื™ื™ึทื˜ ืื™ื– ื ื™ืฉื˜ ื“ื™ ืฉื™ืขื•ืจ!", ืึธื“ืขืจ ืึท ื‘ื™ืกืœ ื•ื•ืขื’ืŸ ืจืขืงื•ืจืกื™ืึธืŸ

ืจืขืงื•ืจืกื™ืึธืŸ - ืึท ื–ื™ื™ืขืจ ืฉื˜ืึทืจืง ืื•ืŸ ื‘ืึทืงื•ื•ืขื ืžืขืงืึทื ื™ื–ืึทื ืื•ื™ื‘ ื“ื™ ื–ืขืœื‘ืข "ื˜ื™ืคืงื™ื™ึทื˜" ืึทืงืฉืึทื ื– ื–ืขื ืขืŸ ื“ื•ืจื›ื’ืขืงืึธื›ื˜ ืื•ื™ืฃ ืคึฟืึทืจื‘ื•ื ื“ืขื ืข ื“ืึทื˜ืŸ. ืึธื‘ืขืจ ืึทื ืงืึทื ื˜ืจืึธื•ืœื“ ืจืขืงื•ืจืกื™ืึธืŸ ืื™ื– ืึท ื‘ื™ื™ื– ื•ื•ืึธืก ืงืขื ืขืŸ ืคื™ืจืŸ ืฆื• ื™ืขื“ืขืจ ืกืึธืฃ ื“ื•ืจื›ืคื™ืจื•ื ื’ ืคึผืจืึธืฆืขืก, ืึธื“ืขืจ (ื•ื•ืึธืก ื›ืึทืคึผืึทื ื– ืžืขืจ ืึธืคื˜) ืฆื• "ืขืกืŸ" ืึทืœืข ื‘ื ื™ืžืฆื ื–ื›ึผืจื•ืŸ.

PostgreSQL Antipatterns: "ื•ืžืขื ื“ื™ืงื™ื™ึทื˜ ืื™ื– ื ื™ืฉื˜ ื“ื™ ืฉื™ืขื•ืจ!", ืึธื“ืขืจ ืึท ื‘ื™ืกืœ ื•ื•ืขื’ืŸ ืจืขืงื•ืจืกื™ืึธืŸ
DBMS ืื™ืŸ ื“ืขื ืึทื›ื˜ื•ื ื’ ืึทืจื‘ืขื˜ ืื•ื™ืฃ ื“ื™ ื–ืขืœื‘ืข ืคึผืจื™ื ืฆื™ืคึผืŸ - "ื–ื™ื™ ื”ืึธื‘ืŸ ืžื™ืจ ื’ืขื–ืึธื’ื˜ ืฆื• ื’ืจืึธื‘ืŸ, ืึทื–ื•ื™ ืื™ืš ื’ืจืึธื‘ืŸ". ื“ื™ื™ืŸ ื‘ืงืฉื” ืงืขื ืขืŸ ื ื™ื˜ ื‘ืœื•ื™ื– ืคึผืึทืžืขืœืขืš ื“ื™ ืืจื•ืžื™ืงืข ืคึผืจืึทืกืขืกืึทื–, ืงืขืกื™ื™ื“ืขืจ ื ืขืžืขืŸ ืคึผืจืึทืกืขืกืขืจ ืจืขืกื•ืจืกืŸ, ืึธื‘ืขืจ ืื•ื™ืš "ืคืึทืœืŸ" ื“ื™ ื’ืื ืฆืข ื“ืึทื˜ืึทื‘ื™ื™ืก, "ืขืกืŸ" ืึทืœืข ื‘ื ื™ืžืฆื ื–ื›ึผืจื•ืŸ. ืฉื•ืฅ ืงืขื’ืŸ ื™ื ืคืึทื ืึทื˜ ืจืขืงื•ืจืกื™ืึธืŸ - ื“ื™ ืคึฟืึทืจืึทื ื˜ื•ื•ืึธืจื˜ืœืขื›ืงื™ื™ื˜ ืคื•ืŸ ื“ื™ ื“ืขื•ื•ืขืœืึธืคึผืขืจ ื–ื™ืš.

ืื™ืŸ 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;

ื ื™ืฆืŸ 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);

PostgreSQL Antipatterns: "ื•ืžืขื ื“ื™ืงื™ื™ึทื˜ ืื™ื– ื ื™ืฉื˜ ื“ื™ ืฉื™ืขื•ืจ!", ืึธื“ืขืจ ืึท ื‘ื™ืกืœ ื•ื•ืขื’ืŸ ืจืขืงื•ืจืกื™ืึธืŸ
ื ื•, ืึท ื˜ื™ืคึผื™ืฉ ื‘ืงืฉื” ืฆื• ืึธืคึผืœืึธื“ื™ืจืŸ ืึทืœืข ืึทืจื˜ื™ืงืœืขืŸ ืื•ื™ืฃ ืื™ื™ืŸ ื˜ืขืžืข ืงื•ืงื˜ ืขืคึผืขืก ื•ื•ื™ ื“ืึธืก:

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 Antipatterns: "ื•ืžืขื ื“ื™ืงื™ื™ึทื˜ ืื™ื– ื ื™ืฉื˜ ื“ื™ ืฉื™ืขื•ืจ!", ืึธื“ืขืจ ืึท ื‘ื™ืกืœ ื•ื•ืขื’ืŸ ืจืขืงื•ืจืกื™ืึธืŸ
ืื™ืฆื˜ ืื•ื ื“ื–ืขืจ ื’ืื ืฆืข ืจืขืงื•ืจืกื™ื•ื•ืข ืึธื ืคึฟืจืขื’ ืงืขื ืขืŸ ื–ื™ื™ืŸ ืจื™ื“ื•ืกื˜ ืฆื• ืคึผื•ื ืงื˜ ื“ืขื:

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 Antipatterns: "ื•ืžืขื ื“ื™ืงื™ื™ึทื˜ ืื™ื– ื ื™ืฉื˜ ื“ื™ ืฉื™ืขื•ืจ!", ืึธื“ืขืจ ืึท ื‘ื™ืกืœ ื•ื•ืขื’ืŸ ืจืขืงื•ืจืกื™ืึธืŸื–ืขืŸ "ื“ื™ ืคึผืจืึธื‘ืœืขื ืคื•ืŸ ื’ืจื™ื™ื ื– ืื•ื™ืฃ ืึท ื˜ืฉืขืกื‘ืึธืจื“"

ื’ืึทืจื“ื™ืึทืŸ ืคื•ืŸ ื“ื™ "ื“ืจืš"

ืึธืœื˜ืขืจื ืึทื˜ืœื™ ืœื™ื™ื’ืŸ ืึทืœืข ื“ื™ ืึทื‘ื“ื–ืฉืขืงืฅ ื•ื•ืึธืก ืžื™ืจ ื”ืึธื‘ืŸ ื’ืขืคึผืœืึธื ื˜ืขืจื˜ ืื•ื™ืฃ ื“ื™ ืจืขืงื•ืจืกื™ืึธืŸ ื“ืจืš ืื™ืŸ ืึท ืžืขื ื’ืข, ื•ื•ืึธืก ืื™ื– ืึท ื™ื™ื ืฆื™ืง "ื“ืจืš" ืฆื• ืขืก:

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

ืคึผืจืึธ: ืื•ื™ื‘ ืขืก ืื™ื– ืึท ืฆื™ืงืœ ืื™ืŸ ื“ื™ ื“ืึทื˜ืŸ, ืžื™ืจ ืœืขื’ืึทืžืจืข ื•ื•ืขื˜ ื ื™ืฉื˜ ืคึผืจืึธืฆืขืก ื“ื™ ื–ืขืœื‘ืข ืจืขืงืึธืจื“ ืจื™ืคึผื™ื˜ื™ื“ืœื™ ืื™ืŸ ื“ืขืจ ื–ืขืœื‘ื™ืงืขืจ ื“ืจืš.
ืงืึธื ืก: ืึธื‘ืขืจ ืื™ืŸ ื“ืขืจ ื–ืขืœื‘ื™ืงืขืจ ืฆื™ื™ื˜, ืžื™ืจ ืงืขื ืขืŸ ืžืžืฉ ื‘ื™ื™ืคึผืึทืก ืึทืœืข ื“ื™ ืจืขืงืึธืจื“ืก ืึธืŸ ืจื™ืคึผื™ื˜ื™ื ื’ ื–ื™ืš.

PostgreSQL Antipatterns: "ื•ืžืขื ื“ื™ืงื™ื™ึทื˜ ืื™ื– ื ื™ืฉื˜ ื“ื™ ืฉื™ืขื•ืจ!", ืึธื“ืขืจ ืึท ื‘ื™ืกืœ ื•ื•ืขื’ืŸ ืจืขืงื•ืจืกื™ืึธืŸื–ืขืŸ "ื ื™ื™ื˜ ืก ืžืึทืš ืคึผืจืึธื‘ืœืขื"

ื“ืจืš ืœืขื ื’ ืœื™ืžื™ื˜

ืฆื• ื•ื™ืกืžื™ื™ื“ืŸ ื“ื™ ืกื™ื˜ื•ืึทืฆื™ืข ืคื•ืŸ โ€‹โ€‹ืจืขืงื•ืจืกื™ืึธืŸ "ื•ื•ืึทื ื“ืขืจื™ื ื’" ืื™ืŸ ืึท ืื•ืžืคืึทืจืฉื˜ืขื ื“ืœืขืš ื˜ื™ืคืงื™ื™ึทื˜, ืžื™ืจ ืงืขื ืขืŸ ืคืึทืจื‘ื™ื ื“ืŸ ื“ื™ ืฆื•ื•ื™ื™ ืคืจื™ืขืจื“ื™ืงืข ืžืขื˜ื”ืึธื“ืก. ืึธื“ืขืจ, ืื•ื™ื‘ ืžื™ืจ ื˜ืึธืŸ ื ื™ืฉื˜ ื•ื•ืขืœืŸ ืฆื• ืฉื˜ื™ืฆืŸ ื•ืžื ื™ื™ื˜ื™ืง ืคืขืœื“ืขืจ, ื”ืขืกืึธืคืข ื“ื™ ืฆื•ืฉื˜ืึทื ื“ ืคึฟืึทืจ ืงืึทื ื˜ื™ื ื™ื•ื™ื ื’ ื“ื™ ืจืขืงื•ืจืกื™ืึธืŸ ืžื™ื˜ ืึทืŸ ืึธืคึผืฉืึทืฆื•ื ื’ ืคื•ืŸ ื“ื™ ื“ืจืš ืœืขื ื’:

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

ืœื™ื™ื’ืŸ ืึท ื‘ืึทืžืขืจืงื•ื ื’