āĻĒā§‹āĻ¸ā§āĻŸāĻ—ā§āĻ°ā§‡āĻāĻ¸āĻ•āĻŋāĻ‰āĻāĻ˛ āĻ…ā§āĻ¯āĻžāĻ¨ā§āĻŸāĻŋāĻĒā§āĻ¯āĻžāĻŸāĻžāĻ°ā§āĻ¨āĻ¸: "āĻ‡āĻ¨āĻĢāĻŋāĻ¨āĻŋāĻŸāĻŋ āĻ¸ā§€āĻŽāĻž āĻ¨āĻ¯āĻŧ!", āĻŦāĻž āĻĒā§āĻ¨āĻ°āĻžāĻŦā§ƒāĻ¤ā§āĻ¤āĻŋ āĻ¸āĻŽā§āĻĒāĻ°ā§āĻ•ā§‡ āĻāĻ•āĻŸā§

āĻĒā§āĻ¨āĻ°āĻžāĻŦā§ƒāĻ¤ā§āĻ¤āĻŋ - āĻāĻ•āĻŸāĻŋ āĻ–ā§āĻŦ āĻļāĻ•ā§āĻ¤āĻŋāĻļāĻžāĻ˛ā§€ āĻāĻŦāĻ‚ āĻ¸ā§āĻŦāĻŋāĻ§āĻžāĻœāĻ¨āĻ• āĻĒā§āĻ°āĻ•ā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻ¯āĻĻāĻŋ āĻāĻ•āĻ‡ "āĻ—āĻ­ā§€āĻ°āĻ­āĻžāĻŦā§‡" āĻ•ā§āĻ°āĻŋāĻ¯āĻŧāĻžāĻ—ā§āĻ˛āĻŋ āĻ¸āĻŽā§āĻĒāĻ°ā§āĻ•āĻŋāĻ¤ āĻĄā§‡āĻŸāĻžāĻ¤ā§‡ āĻ¸āĻžā§āĻšāĻžāĻ˛āĻŋāĻ¤ āĻšāĻ¯āĻŧāĨ¤ āĻ•āĻŋāĻ¨ā§āĻ¤ā§ āĻ…āĻ¨āĻŋāĻ¯āĻŧāĻ¨ā§āĻ¤ā§āĻ°āĻŋāĻ¤ āĻĒā§āĻ¨āĻ°āĻžāĻŦā§ƒāĻ¤ā§āĻ¤āĻŋ āĻāĻ•āĻŸāĻŋ āĻŽāĻ¨ā§āĻĻ āĻ¯āĻž āĻ‰āĻ­āĻ¯āĻŧā§‡āĻ° āĻĻāĻŋāĻ•ā§‡āĻ‡ āĻ¨āĻŋāĻ¯āĻŧā§‡ āĻ¯ā§‡āĻ¤ā§‡ āĻĒāĻžāĻ°ā§‡ āĻ…āĻ¨ā§āĻ¤āĻšā§€āĻ¨ āĻŽā§ƒāĻ¤ā§āĻ¯ā§āĻĻāĻ¨ā§āĻĄ āĻĒā§āĻ°āĻ•ā§āĻ°āĻŋāĻ¯āĻŧāĻž, āĻŦāĻž (āĻ¯āĻž āĻĒā§āĻ°āĻžāĻ¯āĻŧāĻļāĻ‡ āĻ˜āĻŸā§‡) āĻĨā§‡āĻ•ā§‡ "āĻ–āĻžāĻ“āĻ¯āĻŧāĻž" āĻ¸āĻŽāĻ¸ā§āĻ¤ āĻ‰āĻĒāĻ˛āĻŦā§āĻ§ āĻŽā§‡āĻŽāĻ°āĻŋ.

āĻĒā§‹āĻ¸ā§āĻŸāĻ—ā§āĻ°ā§‡āĻāĻ¸āĻ•āĻŋāĻ‰āĻāĻ˛ āĻ…ā§āĻ¯āĻžāĻ¨ā§āĻŸāĻŋāĻĒā§āĻ¯āĻžāĻŸāĻžāĻ°ā§āĻ¨āĻ¸: "āĻ‡āĻ¨āĻĢāĻŋāĻ¨āĻŋāĻŸāĻŋ āĻ¸ā§€āĻŽāĻž āĻ¨āĻ¯āĻŧ!", āĻŦāĻž āĻĒā§āĻ¨āĻ°āĻžāĻŦā§ƒāĻ¤ā§āĻ¤āĻŋ āĻ¸āĻŽā§āĻĒāĻ°ā§āĻ•ā§‡ āĻāĻ•āĻŸā§
āĻāĻ‡ āĻŦāĻŋāĻˇāĻ¯āĻŧā§‡ āĻĄāĻŋāĻŦāĻŋāĻāĻŽāĻāĻ¸ āĻāĻ•āĻ‡ āĻ¨ā§€āĻ¤āĻŋāĻ¤ā§‡ āĻ•āĻžāĻœ āĻ•āĻ°ā§‡ - "āĻ¤āĻžāĻ°āĻž āĻ†āĻŽāĻžāĻ•ā§‡ āĻ–āĻ¨āĻ¨ āĻ•āĻ°āĻ¤ā§‡ āĻŦāĻ˛ā§‡āĻ›āĻŋāĻ˛, āĻ¤āĻžāĻ‡ āĻ†āĻŽāĻŋ āĻ–āĻ¨āĻ¨ āĻ•āĻ°āĻŋ"āĨ¤ āĻ†āĻĒāĻ¨āĻžāĻ° āĻ…āĻ¨ā§āĻ°ā§‹āĻ§ āĻļā§āĻ§ā§āĻŽāĻžāĻ¤ā§āĻ° āĻĒā§āĻ°āĻ¤āĻŋāĻŦā§‡āĻļā§€ āĻĒā§āĻ°āĻ•ā§āĻ°āĻŋāĻ¯āĻŧāĻžāĻ—ā§āĻ˛āĻŋāĻ•ā§‡ āĻ§ā§€āĻ° āĻ•āĻ°ā§‡ āĻĻāĻŋāĻ¤ā§‡ āĻĒāĻžāĻ°ā§‡ āĻ¨āĻž, āĻ•ā§āĻ°āĻŽāĻžāĻ—āĻ¤ āĻĒā§āĻ°āĻ¸ā§‡āĻ¸āĻ°ā§‡āĻ° āĻ¸āĻ‚āĻ¸ā§āĻĨāĻžāĻ¨āĻ—ā§āĻ˛āĻŋ āĻ—ā§āĻ°āĻšāĻŖ āĻ•āĻ°āĻ¤ā§‡ āĻĒāĻžāĻ°ā§‡, āĻ¤āĻŦā§‡ āĻ¸āĻŽāĻ—ā§āĻ° āĻĄāĻžāĻŸāĻžāĻŦā§‡āĻ¸āĻ•ā§‡ "āĻĄā§āĻ°āĻĒ" āĻ•āĻ°āĻ¤ā§‡ āĻĒāĻžāĻ°ā§‡, āĻ¸āĻŽāĻ¸ā§āĻ¤ āĻ‰āĻĒāĻ˛āĻŦā§āĻ§ āĻŽā§‡āĻŽāĻ°āĻŋ "āĻ–āĻžāĻšā§āĻ›ā§‡"āĨ¤ āĻ…āĻ¸ā§€āĻŽ āĻĒā§āĻ¨āĻ°āĻžāĻŦā§ƒāĻ¤ā§āĻ¤āĻŋāĻ° āĻŦāĻŋāĻ°ā§āĻĻā§āĻ§ā§‡ āĻ¸ā§āĻ°āĻ•ā§āĻˇāĻž - āĻŦāĻŋāĻ•āĻžāĻļāĻ•āĻžāĻ°ā§€ āĻ¨āĻŋāĻœā§‡āĻ‡ āĻĻāĻžāĻ¯āĻŧāĻŋāĻ¤ā§āĻŦāĨ¤

PostgreSQL-āĻ, āĻāĻ° āĻŽāĻžāĻ§ā§āĻ¯āĻŽā§‡ āĻĒā§āĻ¨āĻ°āĻžāĻŦā§ƒāĻ¤ā§āĻ¤āĻŋāĻŽā§‚āĻ˛āĻ• āĻĒā§āĻ°āĻļā§āĻ¨āĻ—ā§āĻ˛āĻŋ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°āĻžāĻ° āĻ•ā§āĻˇāĻŽāĻ¤āĻž WITH RECURSIVE āĻ¸āĻ‚āĻ¸ā§āĻ•āĻ°āĻŖ 8.4 āĻāĻ° āĻ…āĻ¨āĻžāĻĻāĻŋ āĻ¸āĻŽāĻ¯āĻŧā§‡āĻ° āĻŽāĻ§ā§āĻ¯ā§‡ āĻ‰āĻĒāĻ¸ā§āĻĨāĻŋāĻ¤ āĻšāĻ¯āĻŧā§‡āĻ›āĻŋāĻ˛, āĻ•āĻŋāĻ¨ā§āĻ¤ā§ āĻ†āĻĒāĻ¨āĻŋ āĻāĻ–āĻ¨āĻ“ āĻ¨āĻŋāĻ¯āĻŧāĻŽāĻŋāĻ¤āĻ­āĻžāĻŦā§‡ āĻ¸āĻŽā§āĻ­āĻžāĻŦā§āĻ¯ āĻĻā§āĻ°ā§āĻŦāĻ˛ "āĻ°āĻ•ā§āĻˇāĻžāĻšā§€āĻ¨" āĻĒā§āĻ°āĻļā§āĻ¨ā§‡āĻ° āĻ¸āĻŽā§āĻŽā§āĻ–ā§€āĻ¨ āĻšāĻ¤ā§‡ āĻĒāĻžāĻ°ā§‡āĻ¨āĨ¤ āĻ•āĻŋāĻ­āĻžāĻŦā§‡ āĻāĻ‡ āĻ§āĻ°āĻ¨ā§‡āĻ° āĻ¸āĻŽāĻ¸ā§āĻ¯āĻž āĻĨā§‡āĻ•ā§‡ āĻ¨āĻŋāĻœā§‡āĻ•ā§‡ āĻĒāĻ°āĻŋāĻ¤ā§āĻ°āĻžāĻŖ āĻĒā§‡āĻ¤ā§‡?

āĻĒā§āĻ¨āĻ°āĻžāĻŦā§ƒāĻ¤ā§āĻ¤āĻŋāĻŽā§‚āĻ˛āĻ• āĻĒā§āĻ°āĻļā§āĻ¨ āĻ˛āĻŋāĻ–āĻŦā§‡āĻ¨ āĻ¨āĻž

āĻāĻŦāĻ‚ āĻ¨āĻ¨-āĻ°āĻŋāĻ•āĻžāĻ°āĻ¸āĻŋāĻ­ āĻ˛āĻŋāĻ–ā§āĻ¨āĨ¤ āĻŦāĻŋāĻ¨ā§€āĻ¤, āĻ†āĻĒāĻ¨āĻžāĻ° K.O.

āĻ†āĻ¸āĻ˛ā§‡, 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);

āĻĒā§‹āĻ¸ā§āĻŸāĻ—ā§āĻ°ā§‡āĻāĻ¸āĻ•āĻŋāĻ‰āĻāĻ˛ āĻ…ā§āĻ¯āĻžāĻ¨ā§āĻŸāĻŋāĻĒā§āĻ¯āĻžāĻŸāĻžāĻ°ā§āĻ¨āĻ¸: "āĻ‡āĻ¨āĻĢāĻŋāĻ¨āĻŋāĻŸāĻŋ āĻ¸ā§€āĻŽāĻž āĻ¨āĻ¯āĻŧ!", āĻŦāĻž āĻĒā§āĻ¨āĻ°āĻžāĻŦā§ƒāĻ¤ā§āĻ¤āĻŋ āĻ¸āĻŽā§āĻĒāĻ°ā§āĻ•ā§‡ āĻāĻ•āĻŸā§
āĻ āĻŋāĻ• āĻ†āĻ›ā§‡, āĻāĻ•āĻŸāĻŋ āĻŦāĻŋāĻˇāĻ¯āĻŧā§‡ āĻ¸āĻŽāĻ¸ā§āĻ¤ āĻŦāĻžāĻ°ā§āĻ¤āĻž āĻĄāĻžāĻ‰āĻ¨āĻ˛ā§‹āĻĄ āĻ•āĻ°āĻžāĻ° āĻœāĻ¨ā§āĻ¯ āĻāĻ•āĻŸāĻŋ āĻ¸āĻžāĻ§āĻžāĻ°āĻŖ āĻ…āĻ¨ā§āĻ°ā§‹āĻ§ āĻāĻ‡āĻ°āĻ•āĻŽ āĻ•āĻŋāĻ›ā§ āĻĻā§‡āĻ–āĻžāĻ¯āĻŧ:

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

āĻāĻ•āĻŸāĻŋ āĻŽāĻ¨ā§āĻ¤āĻŦā§āĻ¯ āĻœā§āĻĄāĻŧā§āĻ¨