рдкреЛрд╕реНрдЯрдЧреНрд░реЗрдПрд╕рдХреНрдпреВрдПрд▓ рдЕрдБрдЯреАрдкреЕрдЯрд░реНрди: тАЬрдЕрдирдВрдд рд╣реА рдорд░реНрдпрд╛рджрд╛ рдирд╛рд╣реА!тАЭ, рдХрд┐рдВрд╡рд╛ рдкреБрдирд░рд╛рд╡реГрддреНрддреАрдмрджреНрджрд▓ рдереЛрдбреЗрд╕реЗ

рдкреБрдирд░рд╛рд╡реГрддреНрддреА - рд╕рдВрдмрдВрдзрд┐рдд рдбреЗрдЯрд╛рд╡рд░ рд╕рдорд╛рди "рд╕рдЦреЛрд▓" рдХреНрд░рд┐рдпрд╛ рдХреЗрд▓реНрдпрд╛ рдЧреЗрд▓реНрдпрд╛рд╕ рдПрдХ рдЕрддрд┐рд╢рдп рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдЖрдгрд┐ рд╕реЛрдпреАрд╕реНрдХрд░ рдпрдВрддреНрд░рдгрд╛. рдкрд░рдВрддреБ рдЕрдирд┐рдпрдВрддреНрд░рд┐рдд рдкреБрдирд░рд╛рд╡реГрддреНрддреА рд╣реА рдПрдХ рд╡рд╛рдИрдЯ рдЧреЛрд╖реНрдЯ рдЖрд╣реЗ рдЬреА рдПрдХрддрд░ рд╣реЛрдК рд╢рдХрддреЗ рдЕрдВрддрд╣реАрди рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреА рдкреНрд░рдХреНрд░рд┐рдпрд╛, рдХрд┐рдВрд╡рд╛ (рдЬреЗ рдЕрдзрд┐рдХ рд╡реЗрд│рд╛ рдШрдбрддреЗ). рд╕рд░реНрд╡ рдЙрдкрд▓рдмреНрдз рдореЗрдорд░реА "рдЦрд╛рдгреЗ"..

рдкреЛрд╕реНрдЯрдЧреНрд░реЗрдПрд╕рдХреНрдпреВрдПрд▓ рдЕрдБрдЯреАрдкреЕрдЯрд░реНрди: тАЬрдЕрдирдВрдд рд╣реА рдорд░реНрдпрд╛рджрд╛ рдирд╛рд╣реА!тАЭ, рдХрд┐рдВрд╡рд╛ рдкреБрдирд░рд╛рд╡реГрддреНрддреАрдмрджреНрджрд▓ рдереЛрдбреЗрд╕реЗ
рдпрд╛ рд╕рдВрджрд░реНрднрд╛рдд рдбреАрдмреАрдПрдордПрд╕ рд╕рдорд╛рди рддрддреНрддреНрд╡рд╛рдВрд╡рд░ рдХрд╛рд░реНрдп рдХрд░рддреЗ - "рддреНрдпрд╛рдВрдиреА рдорд▓рд╛ рдЦреЛрджрд╛рдпрд▓рд╛ рд╕рд╛рдВрдЧрд┐рддрд▓реЗ, рдореНрд╣рдгреВрди рдореА рдЦреЛрджрд▓реЗ". рддреБрдордЪреА рд╡рд┐рдирдВрддреА рдХреЗрд╡рд│ рд╢реЗрдЬрд╛рд░реАрд▓ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдордВрдж рдХрд░реВ рд╢рдХрдд рдирд╛рд╣реА, рд╕рддрдд рдкреНрд░реЛрд╕реЗрд╕рд░ рд╕рдВрд╕рд╛рдзрдиреЗ рдШреЗрддрд╛рдд, рдкрд░рдВрддреБ рд╕рдВрдкреВрд░реНрдг рдбреЗрдЯрд╛рдмреЗрд╕ "рдбреНрд░реЙрдк" рдХрд░реВ рд╢рдХрддреЗ, рд╕рд░реНрд╡ рдЙрдкрд▓рдмреНрдз рдореЗрдорд░реА "рдЦрд╛рдд" рд╢рдХрддреЗ. рдЕрдирдВрдд рдкреБрдирд░рд╛рд╡реГрддреНрддреАрдкрд╛рд╕реВрди рд╕рдВрд░рдХреНрд╖рдг - рд╡рд┐рдХрд╛рд╕рдХрд╛рдЪреА рд╕реНрд╡рддрдГрдЪреА рдЬрдмрд╛рдмрджрд╛рд░реА.

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;

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

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдЬреЛрдбрд╛