SQL HowTo: เจชเฉเฉฑเจ›-เจ—เจฟเฉฑเจ› เจตเจฟเฉฑเจš เจธเจฟเฉฑเจงเจพ เจ•เฉเจ เจธเจฎเจพเจ‚ เจฒเฉ‚เจช เจฒเจฟเจ–เจฃเจพ, เจœเจพเจ‚ โ€œเจเจฒเฉ€เจฎเฉˆเจ‚เจŸเจฐเฉ€ เจคเจฟเฉฐเจจ-เจชเฉœเจพเจ…โ€

เจธเจฎเฉ‡เจ‚-เจธเจฎเฉ‡เจ‚ 'เจคเฉ‡, เจ•เฉเฉฐเจœเฉ€เจ†เจ‚ เจฆเฉ‡ เจธเจฎเฉ‚เจน เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเจ•เฉ‡ เจธเฉฐเจฌเฉฐเจงเจฟเจค เจกเฉ‡เจŸเจพ เจฆเฉ€ เจ–เฉ‹เจœ เจ•เจฐเจจ เจฆเจพ เจ•เฉฐเจฎ เจชเฉˆเจฆเจพ เจนเฉเฉฐเจฆเจพ เจนเฉˆเฅค เจœเจฆเฉ‹เจ‚ เจคเฉฑเจ• เจธเจพเจจเฉ‚เฉฐ เจฐเจฟเจ•เจพเจฐเจกเจพเจ‚ เจฆเฉ€ เจฒเฉ‹เฉœเฉ€เจ‚เจฆเฉ€ เจ•เฉเฉฑเจฒ เจ—เจฟเจฃเจคเฉ€ เจจเจนเฉ€เจ‚ เจฎเจฟเจฒเจฆเฉ€.

เจธเจญ เจคเฉ‹เจ‚ "เจ…เจธเจฒ เจœเฉ€เจตเจจ" เจ‰เจฆเจพเจนเจฐเจจ เจชเฉเจฐเจฆเจฐเจธเจผเจฟเจค เจ•เจฐเจจเจพ เจนเฉˆ 20 เจธเจญ เจคเฉ‹เจ‚ เจชเฉเจฐเจพเจฃเฉ€เจ†เจ‚ เจธเจฎเฉฑเจธเจฟเจ†เจตเจพเจ‚, เจธเฉ‚เจšเฉ€เจฌเฉฑเจง เจ•เจฐเจฎเจšเจพเจฐเฉ€เจ†เจ‚ เจฆเฉ€ เจธเฉ‚เจšเฉ€ 'เจคเฉ‡ (เจ‰เจฆเจพเจนเจฐเจจ เจฒเจˆ, เจ‡เฉฑเจ• เจกเจฟเจตเฉ€เจœเจผเจจ เจฆเฉ‡ เจ…เฉฐเจฆเจฐ). เจ•เฉฐเจฎ เจฆเฉ‡ เจ–เฉ‡เจคเจฐเจพเจ‚ เจฆเฉ‡ เจธเฉฐเจ–เฉ‡เจช เจธเจพเจฐเจพเจ‚เจธเจผเจพเจ‚ เจตเจพเจฒเฉ‡ เจตเฉฑเจ–-เจตเฉฑเจ– เจชเฉเจฐเจฌเฉฐเจงเจจ "เจกเฉˆเจธเจผเจฌเฉ‹เจฐเจกเจพเจ‚" เจฒเจˆ, เจ‡เฉฑเจ• เจธเจฎเจพเจจ เจตเจฟเจธเจผเจพ เจ…เจ•เจธเจฐ เจฒเฉ‹เฉœเฉ€เจ‚เจฆเจพ เจนเฉเฉฐเจฆเจพ เจนเฉˆเฅค

SQL HowTo: เจชเฉเฉฑเจ›-เจ—เจฟเฉฑเจ› เจตเจฟเฉฑเจš เจธเจฟเฉฑเจงเจพ เจ•เฉเจ เจธเจฎเจพเจ‚ เจฒเฉ‚เจช เจฒเจฟเจ–เจฃเจพ, เจœเจพเจ‚ โ€œเจเจฒเฉ€เจฎเฉˆเจ‚เจŸเจฐเฉ€ เจคเจฟเฉฐเจจ-เจชเฉœเจพเจ…โ€

เจ‡เจธ เจฒเฉ‡เจ– เจตเจฟเฉฑเจš เจ…เจธเฉ€เจ‚ เจ…เจœเจฟเจนเฉ€ เจธเจฎเฉฑเจธเจฟเจ† เจฆเฉ‡ เจ‡เฉฑเจ• "เจญเฉ‹เจฒเฉ‡" เจนเฉฑเจฒ เจฆเฉ‡ PostgreSQL เจตเจฟเฉฑเจš เจฒเจพเจ—เฉ‚ เจ•เจฐเจจ เจจเฉ‚เฉฐ เจตเฉ‡เจ–เจพเจ‚เจ—เฉ‡, เจ‡เฉฑเจ• "เจนเฉเจธเจผเจฟเจ†เจฐ" เจ…เจคเฉ‡ เจฌเจนเฉเจค เจ—เฉเฉฐเจเจฒเจฆเจพเจฐ เจเจฒเจ—เฉ‹เจฐเจฟเจฆเจฎ เจฒเฉฑเจญเฉ‡ เจ—เจ เจกเฉ‡เจŸเจพ เจคเฉ‹เจ‚ เจฌเจพเจนเจฐ เจจเจฟเจ•เจฒเจฃ เจฆเฉ€ เจธเจฅเจฟเจคเฉ€ เจฆเฉ‡ เจจเจพเจฒ SQL เจตเจฟเฉฑเจš "เจฒเฉ‚เจช", เจœเฉ‹ เจ•เจฟ เจ†เจฎ เจตเจฟเจ•เจพเจธ เจ…เจคเฉ‡ เจนเฉ‹เจฐ เจธเจฎเจพเจจ เจฎเจพเจฎเจฒเจฟเจ†เจ‚ เจตเจฟเฉฑเจš เจตเจฐเจคเฉ‹เจ‚ เจฒเจˆ เจฒเจพเจญเจฆเจพเจ‡เจ• เจนเฉ‹ เจธเจ•เจฆเจพ เจนเฉˆเฅค

เจ†เจ‰ เจ‡เจธ เจคเฉ‹เจ‚ เจ‡เฉฑเจ• เจŸเฉˆเจธเจŸ เจกเฉ‡เจŸเจพ เจธเฉˆเจŸ เจฒเฉˆเจ‚เจฆเฉ‡ เจนเจพเจ‚ เจชเจฟเจ›เจฒเฉ‡ เจฒเฉ‡เจ–. เจชเฉเจฐเจฆเจฐเจธเจผเจฟเจค เจฐเจฟเจ•เจพเจฐเจกเจพเจ‚ เจจเฉ‚เฉฐ เจธเจฎเฉ‡เจ‚-เจธเจฎเฉ‡เจ‚ 'เจคเฉ‡ "เจœเฉฐเจชเจฟเฉฐเจ—" เจคเฉ‹เจ‚ เจฐเฉ‹เจ•เจฃ เจฒเจˆ เจœเจฆเฉ‹เจ‚ เจ•เฉเจฐเจฎเจฌเฉฑเจง เจฎเฉเฉฑเจฒ เจฎเฉ‡เจฒ เจ–เจพเจ‚เจฆเฉ‡ เจนเจจ, เจ‡เฉฑเจ• เจชเฉเจฐเจพเจ‡เจฎเจฐเฉ€ เจ•เฉเฉฐเจœเฉ€ เจœเฉ‹เฉœ เจ•เฉ‡ เจตเจฟเจธเจผเจพ เจธเฉ‚เจšเจ•เจพเจ‚เจ• เจฆเจพ เจตเจฟเจธเจคเจพเจฐ เจ•เจฐเฉ‹. เจ‰เจธเฉ‡ เจธเจฎเฉ‡เจ‚, เจ‡เจน เจคเฉเจฐเฉฐเจค เจ‡เจธ เจจเฉ‚เฉฐ เจตเจฟเจฒเฉฑเจ–เจฃเจคเจพ เจฆเฉ‡เจตเฉ‡เจ—เจพ เจ…เจคเฉ‡ เจธเจพเจจเฉ‚เฉฐ เจ—เจฐเฉฐเจŸเฉ€ เจฆเฉ‡เจตเฉ‡เจ—เจพ เจ•เจฟ เจ›เจพเจ‚เจŸเฉ€ เจฆเจพ เจ•เฉเจฐเจฎ เจ…เจธเจชเจธเจผเจŸ เจนเฉˆ:

CREATE INDEX ON task(owner_id, task_date, id);
-- ะฐ ัั‚ะฐั€ั‹ะน - ัƒะดะฐะปะธะผ
DROP INDEX task_owner_id_task_date_idx;

เจœเจฟเจตเฉ‡เจ‚ เจธเฉเจฃเจฟเจ† เจœเจพเจ‚เจฆเจพ เจนเฉˆ, เจคเจฟเจตเฉ‡เจ‚ เจฒเจฟเจ–เจฟเจ† เจœเจพเจ‚เจฆเจพ เจนเฉˆ

เจชเจนเจฟเจฒเจพเจ‚, เจ†เจ“ เจฌเฉ‡เจจเจคเฉ€ เจฆเฉ‡ เจธเจญ เจคเฉ‹เจ‚ เจธเจฐเจฒ เจธเฉฐเจธเจ•เจฐเจฃ เจจเฉ‚เฉฐ เจคเจฟเจ†เจฐ เจ•เจฐเฉ€เจ, เจชเฉเจฐเจฆเจฐเจธเจผเจจ เจ•เจฐเจจ เจตเจพเจฒเจฟเจ†เจ‚ เจฆเฉ€เจ†เจ‚ เจ†เจˆเจกเฉ€ เจชเจพเจธ เจ•เจฐเจฆเฉ‡ เจนเฉ‹เจ เจ‡เจจเจชเฉเจŸ เจชเฉˆเจฐเจพเจฎเฉ€เจŸเจฐ เจตเจœเฉ‹เจ‚ เจเจฐเฉ‡:

SELECT
  *
FROM
  task
WHERE
  owner_id = ANY('{1,2,4,8,16,32,64,128,256,512}'::integer[])
ORDER BY
  task_date, id
LIMIT 20;

SQL HowTo: เจชเฉเฉฑเจ›-เจ—เจฟเฉฑเจ› เจตเจฟเฉฑเจš เจธเจฟเฉฑเจงเจพ เจ•เฉเจ เจธเจฎเจพเจ‚ เจฒเฉ‚เจช เจฒเจฟเจ–เจฃเจพ, เจœเจพเจ‚ โ€œเจเจฒเฉ€เจฎเฉˆเจ‚เจŸเจฐเฉ€ เจคเจฟเฉฐเจจ-เจชเฉœเจพเจ…โ€
[explanation.tensor.ru 'เจคเฉ‡ เจฆเฉ‡เจ–เฉ‹]

เจฅเฉ‹เฉœเจพ เจ‰เจฆเจพเจธ - เจ…เจธเฉ€เจ‚ เจธเจฟเจฐเจซ 20 เจฐเจฟเจ•เจพเจฐเจกเจพเจ‚ เจฆเจพ เจ†เจฆเฉ‡เจธเจผ เจฆเจฟเฉฑเจคเจพ, เจชเจฐ เจ‡เฉฐเจกเฉˆเจ•เจธ เจธเจ•เฉˆเจจ เจจเฉ‡ เจธเจพเจจเฉ‚เฉฐ เจ‡เจน เจตเจพเจชเจธ เจ•เจฐ เจฆเจฟเฉฑเจคเจพ 960 เจฒเจพเจˆเจจเจพเจ‚, เจœเจฟเจธ เจจเฉ‚เฉฐ เจซเจฟเจฐ เจ›เจพเจ‚เจŸเฉ€ เจตเฉ€ เจ•เจฐเจจเฉ€ เจชเจˆ... เจšเจฒเฉ‹ เจ˜เฉฑเจŸ เจชเฉœเฉเจนเจจ เจฆเฉ€ เจ•เฉ‹เจธเจผเจฟเจธเจผ เจ•เจฐเฉ€เจเฅค

unnest + ARRAY

เจชเจนเจฟเจฒเจพ เจตเจฟเจšเจพเจฐ เจœเฉ‹ เจธเจพเจกเฉ€ เจฎเจฆเจฆ เจ•เจฐเฉ‡เจ—เจพ เจœเฉ‡ เจธเจพเจจเฉ‚เฉฐ เจฒเฉ‹เฉœ เจนเฉˆ เจธเจฟเจฐเจซเจผ 20 เจ•เฉเจฐเจฎเจฌเฉฑเจง เจฐเจฟเจ•เจพเจฐเจก, เจซเจฟเจฐ เจธเจฟเจฐเจซเจผ เจชเฉœเฉเจนเฉ‹ เจนเจฐเฉ‡เจ• เจฒเจˆ เจ‡เฉฑเจ•เฉ‹ เจ•เฉเจฐเจฎ เจตเจฟเฉฑเจš 20 เจคเฉ‹เจ‚ เจตเฉฑเจง เจจเจนเฉ€เจ‚ เจ•เฉเจฐเจฎเจฌเฉฑเจง เจ•เฉเฉฐเจœเฉ€. เจšเฉฐเจ—เจพ, เจ…เจจเฉเจ•เฉ‚เจฒ เจธเฉ‚เจšเจ•เจพเจ‚เจ• (owner_id, task_date, id) เจธเจพเจกเฉ‡ เจ•เฉ‹เจฒ เจนเฉˆเฅค

เจ†เจ‰ เจเจ•เจธเจŸเจฐเฉˆเจ•เจŸ เจ•เจฐเจจ เจ…เจคเฉ‡ "เจ•เจพเจฒเจฎเจพเจ‚ เจตเจฟเฉฑเจš เจซเฉˆเจฒเจพเจ‰เจฃ" เจฒเจˆ เจ‰เจธเฉ‡ เจตเจฟเจงเฉ€ เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเฉ€เจเฅค เจ…เจŸเฉเฉฑเจŸ เจธเจพเจฐเจฃเฉ€ เจฐเจฟเจ•เจพเจฐเจก, เจ‡เจธ เจคเจฐเจพเจ‚ เจ†เจ–เจฐเฉ€ เจฒเฉ‡เจ–. เจ…เจธเฉ€เจ‚ เจซเฉฐเจ•เจธเจผเจจ เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเจ•เฉ‡ เจ‡เฉฑเจ• เจเจฐเฉ‡ เจตเจฟเฉฑเจš เจซเฉ‹เจฒเจกเจฟเฉฐเจ— เจจเฉ‚เฉฐ เจตเฉ€ เจฒเจพเจ—เฉ‚ เจ•เจฐ เจธเจ•เจฆเฉ‡ เจนเจพเจ‚ ARRAY():

WITH T AS (
  SELECT
    unnest(ARRAY(
      SELECT
        t
      FROM
        task t
      WHERE
        owner_id = unnest
      ORDER BY
        task_date, id
      LIMIT 20 -- ะพะณั€ะฐะฝะธั‡ะธะฒะฐะตะผ ั‚ัƒั‚...
    )) r
  FROM
    unnest('{1,2,4,8,16,32,64,128,256,512}'::integer[])
)
SELECT
  (r).*
FROM
  T
ORDER BY
  (r).task_date, (r).id
LIMIT 20; -- ... ะธ ั‚ัƒั‚ - ั‚ะพะถะต

SQL HowTo: เจชเฉเฉฑเจ›-เจ—เจฟเฉฑเจ› เจตเจฟเฉฑเจš เจธเจฟเฉฑเจงเจพ เจ•เฉเจ เจธเจฎเจพเจ‚ เจฒเฉ‚เจช เจฒเจฟเจ–เจฃเจพ, เจœเจพเจ‚ โ€œเจเจฒเฉ€เจฎเฉˆเจ‚เจŸเจฐเฉ€ เจคเจฟเฉฐเจจ-เจชเฉœเจพเจ…โ€
[explanation.tensor.ru 'เจคเฉ‡ เจฆเฉ‡เจ–เฉ‹]

เจ“เจน, เจชเจนเจฟเจฒเจพเจ‚ เจนเฉ€ เจฌเจนเฉเจค เจตเจงเฉ€เจ†! 40% เจคเฉ‡เจœเจผ เจ…เจคเฉ‡ 4.5 เจ—เฉเจฃเจพ เจ˜เฉฑเจŸ เจกเจพเจŸเจพ เจฎเฉˆเจจเฉ‚เฉฐ เจ‡เจน เจชเฉœเฉเจนเจจเจพ เจชเจฟเจ†เฅค

CTE เจฆเฉเจ†เจฐเจพ เจŸเฉ‡เจฌเจฒ เจฐเจฟเจ•เจพเจฐเจกเจพเจ‚ เจฆเจพ เจชเจฆเจพเจฐเจฅเฉ€เจ•เจฐเจจเจฎเฉˆเจ‚ เจคเฉเจนเจพเจกเจพ เจงเจฟเจ†เจจ เจ‡เจธ เจคเฉฑเจฅ เจตเฉฑเจฒ เจ–เจฟเฉฑเจšเจฆเจพ เจนเจพเจ‚ เจ•เจฟ เจ•เฉเจ เจฎเจพเจฎเจฒเจฟเจ†เจ‚ เจตเจฟเฉฑเจš เจ‡เฉฑเจ• เจธเจฌเจ•เจตเฉ‡เจฐเฉ€ เจตเจฟเฉฑเจš เจ‡เจธเจจเฉ‚เฉฐ เจ–เฉ‹เจœเจฃ เจคเฉ‹เจ‚ เจฌเจพเจ…เจฆ เจ‡เฉฑเจ• เจฐเจฟเจ•เจพเจฐเจก เจฆเฉ‡ เจ–เฉ‡เจคเจฐเจพเจ‚ เจจเจพเจฒ เจคเฉเจฐเฉฐเจค เจ•เฉฐเจฎ เจ•เจฐเจจ เจฆเฉ€ เจ•เฉ‹เจธเจผเจฟเจธเจผ, เจ‡เจธเจจเฉ‚เฉฐ CTE เจตเจฟเฉฑเจš "เจฒเจชเฉ‡เจŸเจฃ" เจคเฉ‹เจ‚ เจฌเจฟเจจเจพเจ‚, เจ‡เจธ เจฆเจพ เจ•เจพเจฐเจจ เจฌเจฃ เจธเจ•เจฆเฉ€ เจนเฉˆ InitPlan "เจ—เฉเจฃเจพ เจ•เจฐเฉ‹" เจ‡เจนเจจเจพเจ‚ เจธเจฎเจพเจจ เจ–เฉ‡เจคเจฐเจพเจ‚ เจฆเฉ€ เจธเฉฐเจ–เจฟเจ† เจฆเฉ‡ เจ…เจจเฉเจชเจพเจคเฉ€:

SELECT
  ((
    SELECT
      t
    FROM
      task t
    WHERE
      owner_id = 1
    ORDER BY
      task_date, id
    LIMIT 1
  ).*);

Result  (cost=4.77..4.78 rows=1 width=16) (actual time=0.063..0.063 rows=1 loops=1)
  Buffers: shared hit=16
  InitPlan 1 (returns $0)
    ->  Limit  (cost=0.42..1.19 rows=1 width=48) (actual time=0.031..0.032 rows=1 loops=1)
          Buffers: shared hit=4
          ->  Index Scan using task_owner_id_task_date_id_idx on task t  (cost=0.42..387.57 rows=500 width=48) (actual time=0.030..0.030 rows=1 loops=1)
                Index Cond: (owner_id = 1)
                Buffers: shared hit=4
  InitPlan 2 (returns $1)
    ->  Limit  (cost=0.42..1.19 rows=1 width=48) (actual time=0.008..0.009 rows=1 loops=1)
          Buffers: shared hit=4
          ->  Index Scan using task_owner_id_task_date_id_idx on task t_1  (cost=0.42..387.57 rows=500 width=48) (actual time=0.008..0.008 rows=1 loops=1)
                Index Cond: (owner_id = 1)
                Buffers: shared hit=4
  InitPlan 3 (returns $2)
    ->  Limit  (cost=0.42..1.19 rows=1 width=48) (actual time=0.008..0.008 rows=1 loops=1)
          Buffers: shared hit=4
          ->  Index Scan using task_owner_id_task_date_id_idx on task t_2  (cost=0.42..387.57 rows=500 width=48) (actual time=0.008..0.008 rows=1 loops=1)
                Index Cond: (owner_id = 1)
                Buffers: shared hit=4"
  InitPlan 4 (returns $3)
    ->  Limit  (cost=0.42..1.19 rows=1 width=48) (actual time=0.009..0.009 rows=1 loops=1)
          Buffers: shared hit=4
          ->  Index Scan using task_owner_id_task_date_id_idx on task t_3  (cost=0.42..387.57 rows=500 width=48) (actual time=0.009..0.009 rows=1 loops=1)
                Index Cond: (owner_id = 1)
                Buffers: shared hit=4

เจ‡เจนเฉ€ เจฐเจฟเจ•เจพเจฐเจก 4 เจตเจพเจฐ "เจตเฉ‡เจ–เจฟเจ† เจ—เจฟเจ†" เจธเฉ€... PostgreSQL 11 เจคเฉฑเจ•, เจ‡เจน เจตเจฟเจตเจนเจพเจฐ เจจเจฟเจฏเจฎเจฟเจค เจคเฉŒเจฐ 'เจคเฉ‡ เจตเจพเจชเจฐเจฆเจพ เจนเฉˆ, เจ…เจคเฉ‡ เจนเฉฑเจฒ เจนเฉˆ เจ‡เจธเจจเฉ‚เฉฐ CTE เจตเจฟเฉฑเจš "เจฒเจชเฉ‡เจŸเจฃเจพ", เจœเฉ‹ เจ•เจฟ เจ‡เจนเจจเจพเจ‚ เจธเฉฐเจธเจ•เจฐเจฃเจพเจ‚ เจตเจฟเฉฑเจš เจ†เจชเจŸเฉ€เจฎเจพเจˆเจœเจผเจฐ เจฒเจˆ เจ‡เฉฑเจ• เจชเฉ‚เจฐเจจ เจธเฉ€เจฎเจพ เจนเฉˆเฅค

เจ†เจตเจฐเจคเฉ€ เจธเฉฐเจšเจตเจ•

เจชเจฟเจ›เจฒเฉ‡ เจธเฉฐเจธเจ•เจฐเจฃ เจตเจฟเฉฑเจš, เจ•เฉเฉฑเจฒ เจฎเจฟเจฒเจพ เจ•เฉ‡ เจ…เจธเฉ€เจ‚ เจชเฉœเฉเจนเจฟเจ† เจนเฉˆ 200 เจฒเจพเจˆเจจเจพเจ‚ เจฒเฉ‹เฉœเฉ€เจ‚เจฆเฉ‡ 20 เจฆเฉ€ เจ–เจผเจพเจคเจฐ. 960 เจจเจนเฉ€เจ‚, เจชเจฐ เจ‡เจธ เจคเฉ‹เจ‚ เจตเฉ€ เจ˜เฉฑเจŸ - เจ•เฉ€ เจ‡เจน เจธเฉฐเจญเจต เจนเฉˆ?

เจ†เจ“ เจ‰เจธ เจ—เจฟเจ†เจจ เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเจจ เจฆเฉ€ เจ•เฉ‹เจธเจผเจฟเจธเจผ เจ•เจฐเฉ€เจ เจœเจฟเจธเจฆเฉ€ เจธเจพเจจเฉ‚เฉฐ เจฒเฉ‹เฉœ เจนเฉˆ เจ•เฉเฉฑเจฒ 20 เจฐเจฟเจ•เจพเจฐเจกเฅค เจญเจพเจต, เจ…เจธเฉ€เจ‚ เจกเฉ‡เจŸเจพ เจฐเฉ€เจกเจฟเฉฐเจ— เจจเฉ‚เฉฐ เจ‰เจฆเฉ‹เจ‚ เจคเฉฑเจ• เจฆเฉเจนเจฐเจพเจตเจพเจ‚เจ—เฉ‡ เจœเจฆเฉ‹เจ‚ เจคเฉฑเจ• เจ…เจธเฉ€เจ‚ เจฒเฉ‹เฉœเฉ€เจ‚เจฆเฉ€ เจฎเจพเจคเจฐเจพ เจคเฉฑเจ• เจจเจนเฉ€เจ‚ เจชเจนเฉเฉฐเจšเจฆเฉ‡เฅค

เจ•เจฆเจฎ 1: เจธเจผเฉเจฐเฉ‚เจ†เจคเฉ€ เจธเฉ‚เจšเฉ€

เจธเจชเฉฑเจธเจผเจŸ เจคเฉŒเจฐ 'เจคเฉ‡, 20 เจฐเจฟเจ•เจพเจฐเจกเจพเจ‚ เจฆเฉ€ เจธเจพเจกเฉ€ "เจจเจฟเจธเจผเจพเจจเจพ" เจธเฉ‚เจšเฉ€ เจธเจพเจกเฉ€ เจฎเจพเจฒเจ•_เจ†เจˆเจกเฉ€ เจ•เฉเฉฐเจœเฉ€เจ†เจ‚ เจตเจฟเฉฑเจšเฉ‹เจ‚ เจ‡เฉฑเจ• เจฒเจˆ "เจชเจนเจฟเจฒเฉ‡" เจฐเจฟเจ•เจพเจฐเจกเจพเจ‚ เจจเจพเจฒ เจธเจผเฉเจฐเฉ‚ เจนเฉ‹เจฃเฉ€ เจšเจพเจนเฉ€เจฆเฉ€ เจนเฉˆเฅค เจ‡เจธ เจฒเจˆ, เจชเจนเจฟเจฒเจพเจ‚ เจ…เจธเฉ€เจ‚ เจ…เจœเจฟเจนเฉ‡ เจฒเฉฑเจญเจพเจ‚เจ—เฉ‡ เจนเจฐเฉ‡เจ• เจ•เฉเฉฐเจœเฉ€ เจฒเจˆ "เจฌเจนเฉเจค เจชเจนเจฟเจฒเจพเจ‚" เจ…เจคเฉ‡ เจ‡เจธเจจเฉ‚เฉฐ เจธเฉ‚เจšเฉ€ เจตเจฟเฉฑเจš เจธเจผเจพเจฎเจฒ เจ•เจฐเฉ‹, เจ‡เจธ เจจเฉ‚เฉฐ เจ‰เจธ เจ•เฉเจฐเจฎ เจตเจฟเฉฑเจš เจ•เฉเจฐเจฎเจฌเฉฑเจง เจ•เจฐเจฆเฉ‡ เจนเฉ‹เจ เจœเฉ‹ เจ…เจธเฉ€เจ‚ เจšเจพเจนเฉเฉฐเจฆเฉ‡ เจนเจพเจ‚ - (task_date, id)เฅค

SQL HowTo: เจชเฉเฉฑเจ›-เจ—เจฟเฉฑเจ› เจตเจฟเฉฑเจš เจธเจฟเฉฑเจงเจพ เจ•เฉเจ เจธเจฎเจพเจ‚ เจฒเฉ‚เจช เจฒเจฟเจ–เจฃเจพ, เจœเจพเจ‚ โ€œเจเจฒเฉ€เจฎเฉˆเจ‚เจŸเจฐเฉ€ เจคเจฟเฉฐเจจ-เจชเฉœเจพเจ…โ€

เจ•เจฆเจฎ 2: "เจ…เจ—เจฒเฉ€" เจเจ‚เจŸเจฐเฉ€เจ†เจ‚ เจฒเฉฑเจญเฉ‹

เจนเฉเจฃ เจœเฉ‡ เจ…เจธเฉ€เจ‚ เจ†เจชเจฃเฉ€ เจธเฉ‚เจšเฉ€ เจตเจฟเฉฑเจšเฉ‹เจ‚ เจชเจนเจฟเจฒเฉ€ เจเจ‚เจŸเจฐเฉ€ เจฒเฉˆเจ‚เจฆเฉ‡ เจนเจพเจ‚ เจ…เจคเฉ‡ เจธเจผเฉเจฐเฉ‚ เจ•เจฐเจฆเฉ‡ เจนเจพเจ‚ เจธเฉ‚เจšเจ•เจพเจ‚เจ• เจฆเฉ‡ เจจเจพเจฒ "เจ•เจฆเจฎ" เจนเฉ‹เจฐ เจ…เฉฑเจ—เฉ‡ เจฎเจพเจฒเจ•_เจ†เจˆเจกเฉ€ เจ•เฉเฉฐเจœเฉ€ เจจเฉ‚เฉฐ เจธเฉเจฐเฉฑเจ–เจฟเจ…เจค เจ•เจฐเจฆเฉ‡ เจนเฉ‹เจ, เจซเจฟเจฐ เจธเจพเจฐเฉ‡ เจฎเจฟเจฒเฉ‡ เจฐเจฟเจ•เจพเจฐเจก เจจเจคเฉ€เจœเฉ‡ เจฆเฉ€ เจšเฉ‹เจฃ เจตเจฟเฉฑเจš เจฌเจฟเจฒเจ•เฉเจฒ เจ…เจ—เจฒเฉ‡ เจนเจจเฅค เจฌเฉ‡เจธเจผเฉฑเจ•, เจธเจฟเจฐเจซเจผ เจœเจฆเฉ‹เจ‚ เจคเฉฑเจ• เจ…เจธเฉ€เจ‚ เจฌเฉฑเจŸ เจ•เฉเฉฐเจœเฉ€ เจจเฉ‚เฉฐ เจชเจพเจฐ เจจเจนเฉ€เจ‚ เจ•เจฐเจฆเฉ‡ เจธเฉ‚เจšเฉ€ เจตเจฟเฉฑเจš เจฆเฉ‚เจœเฉ€ เจเจ‚เจŸเจฐเฉ€เฅค

เจœเฉ‡ เจ‡เจน เจชเจคเจพ เจšเจฒเจฆเจพ เจนเฉˆ เจ•เจฟ เจ…เจธเฉ€เจ‚ เจฆเฉ‚เจœเฉ‡ เจฐเจฟเจ•เจพเจฐเจก เจจเฉ‚เฉฐ "เจชเจพเจฐ" เจ•เจฐ เจฆเจฟเฉฑเจคเจพ เจนเฉˆ, เจคเจพเจ‚ เจชเฉœเฉเจนเฉ€ เจ—เจˆ เจ†เจ–เจฐเฉ€ เจเจ‚เจŸเจฐเฉ€ เจชเจนเจฟเจฒเฉ€ เจฆเฉ€ เจฌเจœเจพเจ เจธเฉ‚เจšเฉ€ เจตเจฟเฉฑเจš เจธเจผเจพเจฎเจฒ เจ•เฉ€เจคเฉ€ เจœเจพเจฃเฉ€ เจšเจพเจนเฉ€เจฆเฉ€ เจนเฉˆ (เจ‰เจธเฉ‡ เจฎเจพเจฒเจ•_เจ†เจˆเจกเฉ€ เจฆเฉ‡ เจจเจพเจฒ), เจœเจฟเจธ เจคเฉ‹เจ‚ เจฌเจพเจ…เจฆ เจ…เจธเฉ€เจ‚ เจธเฉ‚เจšเฉ€ เจจเฉ‚เฉฐ เจฆเฉเจฌเจพเจฐเจพ เจ•เฉเจฐเจฎเจฌเฉฑเจง เจ•เจฐเจฆเฉ‡ เจนเจพเจ‚เฅค

SQL HowTo: เจชเฉเฉฑเจ›-เจ—เจฟเฉฑเจ› เจตเจฟเฉฑเจš เจธเจฟเฉฑเจงเจพ เจ•เฉเจ เจธเจฎเจพเจ‚ เจฒเฉ‚เจช เจฒเจฟเจ–เจฃเจพ, เจœเจพเจ‚ โ€œเจเจฒเฉ€เจฎเฉˆเจ‚เจŸเจฐเฉ€ เจคเจฟเฉฐเจจ-เจชเฉœเจพเจ…โ€

เจญเจพเจต, เจ…เจธเฉ€เจ‚ เจนเจฎเฉ‡เจธเจผเจพเจ‚ เจ‡เจน เจชเฉเจฐเจพเจชเจค เจ•เจฐเจฆเฉ‡ เจนเจพเจ‚ เจ•เจฟ เจธเฉ‚เจšเฉ€ เจตเจฟเฉฑเจš เจนเจฐเฉ‡เจ• เจ•เฉเฉฐเจœเฉ€ เจฒเจˆ เจ‡เฉฑเจ• เจคเฉ‹เจ‚ เจตเฉฑเจง เจเจ‚เจŸเจฐเฉ€ เจจเจนเฉ€เจ‚ เจนเฉˆ (เจœเฉ‡เจ•เจฐ เจเจ‚เจŸเจฐเฉ€เจ†เจ‚ เจ–เจคเจฎ เจนเฉ‹ เจœเจพเจ‚เจฆเฉ€เจ†เจ‚ เจนเจจ เจ…เจคเฉ‡ เจ…เจธเฉ€เจ‚ "เจ•เจฐเจพเจธ" เจจเจนเฉ€เจ‚ เจ•เจฐเจฆเฉ‡ เจนเจพเจ‚, เจคเจพเจ‚ เจธเฉ‚เจšเฉ€ เจตเจฟเฉฑเจšเฉ‹เจ‚ เจชเจนเจฟเจฒเฉ€ เจเจ‚เจŸเจฐเฉ€ เจ—เจพเจ‡เจฌ เจนเฉ‹ เจœเจพเจตเฉ‡เจ—เฉ€ เจ…เจคเฉ‡ เจ•เฉเจ เจตเฉ€ เจธเจผเจพเจฎเจฒ เจจเจนเฉ€เจ‚ เจ•เฉ€เจคเจพ เจœเจพเจตเฉ‡เจ—เจพเฅค ), เจ…เจคเฉ‡ เจ‰เจน เจนเจฎเฉ‡เจธเจผเจพ เจ•เฉเจฐเจฎเจฌเฉฑเจง เจเจชเจฒเฉ€เจ•เฉ‡เจธเจผเจจ เจ•เฉเฉฐเจœเฉ€ (task_date, id) เจฆเฉ‡ เจตเจงเจฆเฉ‡ เจ•เฉเจฐเจฎ เจตเจฟเฉฑเจšเฅค

SQL HowTo: เจชเฉเฉฑเจ›-เจ—เจฟเฉฑเจ› เจตเจฟเฉฑเจš เจธเจฟเฉฑเจงเจพ เจ•เฉเจ เจธเจฎเจพเจ‚ เจฒเฉ‚เจช เจฒเจฟเจ–เจฃเจพ, เจœเจพเจ‚ โ€œเจเจฒเฉ€เจฎเฉˆเจ‚เจŸเจฐเฉ€ เจคเจฟเฉฐเจจ-เจชเฉœเจพเจ…โ€

เจ•เจฆเจฎ 3: เจฐเจฟเจ•เจพเจฐเจกเจพเจ‚ เจจเฉ‚เฉฐ เจซเจฟเจฒเจŸเจฐ เจ•เจฐเฉ‹ เจ…เจคเฉ‡ "เจตเจฟเจธเจคเจพเจฐ เจ•เจฐเฉ‹"

เจธเจพเจกเฉ‡ เจ†เจตเจฐเจคเฉ€ เจšเฉ‹เจฃ เจฆเฉ‡ เจ•เฉเจ เจ•เจคเจพเจฐเจพเจ‚ เจตเจฟเฉฑเจš, เจ•เฉเจ เจฐเจฟเจ•เจพเจฐเจก rv เจกเฉเจชเจฒเฉ€เจ•เฉ‡เจŸ เจนเจจ - เจชเจนเจฟเจฒเจพเจ‚ เจ…เจธเฉ€เจ‚ "เจธเฉ‚เจšเฉ€ เจฆเฉ€ เจฆเฉ‚เจœเฉ€ เจเจ‚เจŸเจฐเฉ€ เจฆเฉ€ เจฌเจพเจฐเจกเจฐ เจชเจพเจฐ เจ•เจฐเจจเจพ" เจตเจฐเจ—เฉ‡ เจฒเฉฑเจญเจฆเฉ‡ เจนเจพเจ‚, เจ…เจคเฉ‡ เจซเจฟเจฐ เจ‡เจธเจจเฉ‚เฉฐ เจธเฉ‚เจšเฉ€ เจตเจฟเฉฑเจšเฉ‹เจ‚ 2 เจฆเฉ‡ เจคเฉŒเจฐ 'เจคเฉ‡ เจฌเจฆเจฒเจฆเฉ‡ เจนเจพเจ‚เฅค เจ‡เจธ เจฒเจˆ เจชเจนเจฟเจฒเฉ€ เจ˜เจŸเจจเจพ เจจเฉ‚เฉฐ เจซเจฟเจฒเจŸเจฐ เจ•เจฐเจจ เจฆเฉ€ เจฒเฉ‹เฉœ เจนเฉˆ.

เจ–เจผเฉŒเจซเจผเจจเจพเจ• เจ…เฉฐเจคเจฟเจฎ เจชเฉเฉฑเจ›เจ—เจฟเฉฑเจ›

WITH RECURSIVE T AS (
  -- #1 : ะทะฐะฝะพัะธะผ ะฒ ัะฟะธัะพะบ "ะฟะตั€ะฒั‹ะต" ะทะฐะฟะธัะธ ะฟะพ ะบะฐะถะดะพะผัƒ ะธะท ะบะปัŽั‡ะตะน ะฝะฐะฑะพั€ะฐ
  WITH wrap AS ( -- "ะผะฐั‚ะตั€ะธะฐะปะธะทัƒะตะผ" record'ั‹, ั‡ั‚ะพะฑั‹ ะพะฑั€ะฐั‰ะตะฝะธะต ะบ ะฟะพะปัะผ ะฝะต ะฒั‹ะทั‹ะฒะฐะปะพ ัƒะผะฝะพะถะตะฝะธั InitPlan/SubPlan
    WITH T AS (
      SELECT
        (
          SELECT
            r
          FROM
            task r
          WHERE
            owner_id = unnest
          ORDER BY
            task_date, id
          LIMIT 1
        ) r
      FROM
        unnest('{1,2,4,8,16,32,64,128,256,512}'::integer[])
    )
    SELECT
      array_agg(r ORDER BY (r).task_date, (r).id) list -- ัะพั€ั‚ะธั€ัƒะตะผ ัะฟะธัะพะบ ะฒ ะฝัƒะถะฝะพะผ ะฟะพั€ัะดะบะต
    FROM
      T
  )
  SELECT
    list
  , list[1] rv
  , FALSE not_cross
  , 0 size
  FROM
    wrap
UNION ALL
  -- #2 : ะฒั‹ั‡ะธั‚ั‹ะฒะฐะตะผ ะทะฐะฟะธัะธ 1-ะณะพ ะฟะพ ะฟะพั€ัะดะบัƒ ะบะปัŽั‡ะฐ, ะฟะพะบะฐ ะฝะต ะฟะตั€ะตัˆะฐะณะฝะตะผ ั‡ะตั€ะตะท ะทะฐะฟะธััŒ 2-ะณะพ
  SELECT
    CASE
      -- ะตัะปะธ ะฝะธั‡ะตะณะพ ะฝะต ะฝะฐะนะดะตะฝะพ ะดะปั ะบะปัŽั‡ะฐ 1-ะน ะทะฐะฟะธัะธ
      WHEN X._r IS NOT DISTINCT FROM NULL THEN
        T.list[2:] -- ัƒะฑะธั€ะฐะตะผ ะตะต ะธะท ัะฟะธัะบะฐ
      -- ะตัะปะธ ะผั‹ ะะ• ะฟะตั€ะตัะตะบะปะธ ะฟั€ะธะบะปะฐะดะฝะพะน ะบะปัŽั‡ 2-ะน ะทะฐะฟะธัะธ
      WHEN X.not_cross THEN
        T.list -- ะฟั€ะพัั‚ะพ ะฟั€ะพั‚ัะณะธะฒะฐะตะผ ั‚ะพั‚ ะถะต ัะฟะธัะพะบ ะฑะตะท ะผะพะดะธั„ะธะบะฐั†ะธะน
      -- ะตัะปะธ ะฒ ัะฟะธัะบะต ัƒะถะต ะฝะตั‚ 2-ะน ะทะฐะฟะธัะธ
      WHEN T.list[2] IS NULL THEN
        -- ะฟั€ะพัั‚ะพ ะฒะพะทะฒั€ะฐั‰ะฐะตะผ ะฟัƒัั‚ะพะน ัะฟะธัะพะบ
        '{}'
      -- ะฟะตั€ะตัะพั€ั‚ะธั€ะพะฒั‹ะฒะฐะตะผ ัะปะพะฒะฐั€ัŒ, ัƒะฑะธั€ะฐั 1-ัŽ ะทะฐะฟะธััŒ ะธ ะดะพะฑะฐะฒะปัั ะฟะพัะปะตะดะฝัŽัŽ ะธะท ะฝะฐะนะดะตะฝะฝั‹ั…
      ELSE (
        SELECT
          coalesce(T.list[2] || array_agg(r ORDER BY (r).task_date, (r).id), '{}')
        FROM
          unnest(T.list[3:] || X._r) r
      )
    END
  , X._r
  , X.not_cross
  , T.size + X.not_cross::integer
  FROM
    T
  , LATERAL(
      WITH wrap AS ( -- "ะผะฐั‚ะตั€ะธะฐะปะธะทัƒะตะผ" record
        SELECT
          CASE
            -- ะตัะปะธ ะฒัะต-ั‚ะฐะบะธ "ะฟะตั€ะตัˆะฐะณะฝัƒะปะธ" ั‡ะตั€ะตะท 2-ัŽ ะทะฐะฟะธััŒ
            WHEN NOT T.not_cross
              -- ั‚ะพ ะฝัƒะถะฝะฐั ะทะฐะฟะธััŒ - ะฟะตั€ะฒะฐั ะธะท ัะฟะฟะธัะบะฐ
              THEN T.list[1]
            ELSE ( -- ะตัะปะธ ะฝะต ะฟะตั€ะตัะตะบะปะธ, ั‚ะพ ะบะปัŽั‡ ะพัั‚ะฐะปัั ะบะฐะบ ะฒ ะฟั€ะตะดั‹ะดัƒั‰ะตะน ะทะฐะฟะธัะธ - ะพั‚ั‚ะฐะปะบะธะฒะฐะตะผัั ะพั‚ ะฝะตะต
              SELECT
                _r
              FROM
                task _r
              WHERE
                owner_id = (rv).owner_id AND
                (task_date, id) > ((rv).task_date, (rv).id)
              ORDER BY
                task_date, id
              LIMIT 1
            )
          END _r
      )
      SELECT
        _r
      , CASE
          -- ะตัะปะธ 2-ะน ะทะฐะฟะธัะธ ัƒะถะต ะฝะตั‚ ะฒ ัะฟะธัะบะต, ะฝะพ ะผั‹ ั…ะพั‚ัŒ ั‡ั‚ะพ-ั‚ะพ ะฝะฐัˆะปะธ
          WHEN list[2] IS NULL AND _r IS DISTINCT FROM NULL THEN
            TRUE
          ELSE -- ะฝะธั‡ะตะณะพ ะฝะต ะฝะฐัˆะปะธ ะธะปะธ "ะฟะตั€ะตัˆะฐะณะฝัƒะปะธ"
            coalesce(((_r).task_date, (_r).id) < ((list[2]).task_date, (list[2]).id), FALSE)
        END not_cross
      FROM
        wrap
    ) X
  WHERE
    T.size < 20 AND -- ะพะณั€ะฐะฝะธั‡ะธะฒะฐะตะผ ั‚ัƒั‚ ะบะพะปะธั‡ะตัั‚ะฒะพ
    T.list IS DISTINCT FROM '{}' -- ะธะปะธ ะฟะพะบะฐ ัะฟะธัะพะบ ะฝะต ะบะพะฝั‡ะธะปัั
)
-- #3 : "ั€ะฐะทะฒะพั€ะฐั‡ะธะฒะฐะตะผ" ะทะฐะฟะธัะธ - ะฟะพั€ัะดะพะบ ะณะฐั€ะฐะฝั‚ะธั€ะพะฒะฐะฝ ะฟะพ ะฟะพัั‚ั€ะพะตะฝะธัŽ
SELECT
  (rv).*
FROM
  T
WHERE
  not_cross; -- ะฑะตั€ะตะผ ั‚ะพะปัŒะบะพ "ะฝะตะฟะตั€ะตัะตะบะฐัŽั‰ะธะต" ะทะฐะฟะธัะธ

SQL HowTo: เจชเฉเฉฑเจ›-เจ—เจฟเฉฑเจ› เจตเจฟเฉฑเจš เจธเจฟเฉฑเจงเจพ เจ•เฉเจ เจธเจฎเจพเจ‚ เจฒเฉ‚เจช เจฒเจฟเจ–เจฃเจพ, เจœเจพเจ‚ โ€œเจเจฒเฉ€เจฎเฉˆเจ‚เจŸเจฐเฉ€ เจคเจฟเฉฐเจจ-เจชเฉœเจพเจ…โ€
[explanation.tensor.ru 'เจคเฉ‡ เจฆเฉ‡เจ–เฉ‹]

เจ‡เจธ เจคเจฐเฉเจนเจพเจ‚, เจ…เจธเฉ€เจ‚ เจเจ—เจœเจผเฉ€เจ•เจฟเจŠเจธเจผเจจ เจŸเจพเจˆเจฎ เจฆเฉ‡ 50% เจฒเจˆ 20% เจกเจพเจŸเจพ เจฐเฉ€เจก เจ•เฉ€เจคเจพ เจ—เจฟเจ†. เจญเจพเจต, เจœเฉ‡เจ•เจฐ เจคเฉเจนเจพเจกเฉ‡ เจ•เฉ‹เจฒ เจ‡เจน เจตเจฟเจธเจผเจตเจพเจธ เจ•เจฐเจจ เจฆเฉ‡ เจ•เจพเจฐเจจ เจนเจจ เจ•เจฟ เจชเฉœเฉเจนเจจ เจตเจฟเฉฑเจš เจฌเจนเฉเจค เจธเจฎเจพเจ‚ เจฒเฉฑเจ— เจธเจ•เจฆเจพ เจนเฉˆ (เจ‰เจฆเจพเจนเจฐเจฃ เจตเจœเฉ‹เจ‚, เจกเฉ‡เจŸเจพ เจ…เจ•เจธเจฐ เจ•เฉˆเจธเจผ เจตเจฟเฉฑเจš เจจเจนเฉ€เจ‚ เจนเฉเฉฐเจฆเจพ เจนเฉˆ, เจ…เจคเฉ‡ เจคเฉเจนเจพเจจเฉ‚เฉฐ เจ‡เจธเจฆเฉ‡ เจฒเจˆ เจกเจฟเจธเจ• 'เจคเฉ‡ เจœเจพเจฃเจพ เจชเฉˆเจ‚เจฆเจพ เจนเฉˆ), เจคเจพเจ‚ เจ‡เจธ เจคเจฐเฉเจนเจพเจ‚ เจคเฉเจธเฉ€เจ‚ เจชเฉœเฉเจนเจจ 'เจคเฉ‡ เจ˜เฉฑเจŸ เจจเจฟเจฐเจญเจฐ เจ•เจฐ เจธเจ•เจฆเฉ‡ เจนเฉ‹เฅค .

เจ•เจฟเจธเฉ‡ เจตเฉ€ เจธเจฅเจฟเจคเฉ€ เจตเจฟเฉฑเจš, เจซเจพเจ‚เจธเฉ€ เจฆเจพ เจธเจฎเจพเจ‚ "เจญเฉ‹เจฒเฉ‡" เจชเจนเจฟเจฒเฉ‡ เจตเจฟเจ•เจฒเจช เจจเจพเจฒเฉ‹เจ‚ เจฌเจฟเจนเจคเจฐ เจจเจฟเจ•เจฒเจฟเจ†เฅค เจชเจฐ เจ‡เจนเจจเจพเจ‚ 3 เจตเจฟเจ•เจฒเจชเจพเจ‚ เจตเจฟเฉฑเจšเฉ‹เจ‚ เจ•เจฟเจนเฉœเจพ เจตเจฐเจคเจฃเจพ เจนเฉˆ เจคเฉเจนเจพเจกเฉ‡ 'เจคเฉ‡ เจจเจฟเจฐเจญเจฐ เจ•เจฐเจฆเจพ เจนเฉˆเฅค

เจธเจฐเฉ‹เจค: www.habr.com

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