объединяет не последовательно, то конечная последовательно ломается.
Запрос должен отсортировать по группам (в каждом группе своя сортировка). Если какая-то альтернатива или сразу лучше на аппликейшен уровне сделать ?
WITH cte AS (
(SELECT * FROM table WHERE state = 'first' and planned_at::DATE = current_date ORDER BY checked_at)
UNION ALL
(SELECT * FROM table WHERE state = 'second' and planned_at::DATE = current_date ORDER BY is_first DESC, forward_at)
UNION ALL
(SELECT * FROM table WHERE state = 'third' and planned_at::DATE = current_date ORDER BY runned_at
)
)
SELECT * FROM cte WHERE planned_at::DATE = current_date AND runner_id = '94f08576-6c0f-4836-bbd0-66487d006e03'
Так написать нужный ORDER BY (все ORDER BY, кроме того, который в основном запросе, любая RDBMS имеет право игнорировать, если они влияют только на то, в каком порядке выбираются записи). Т.е. ORDER BY внутри CTE убрать, а в основном запросе написать тот, который нужен (выглядеть он будет некрасиво, да — придётся использовать CASE и т.п.).
в сte сделать select 1 as rn,* union all select 2 as rn,* ... ) select ... order by rn?
конечный order ломает внутренние сортировки для каждой группы
ну вы добавьте row_number то в чем проблема в каждый запрос order by rn, rn_row_number
Это потому, что Вы его не полностью написали (просто "ORDER BY rn" недостаточно, конечно), и даже нам не показали. ;)
в идеале хотелось бы чтобы конечный порядок был как указаны union(но эт мечты). Если добавить row_number и сортировать по ним, то тоже сломается сортировка внутри "группы" :(
я вообще не пойму зачем здесь юнион. select ... from ... where state in ('first','second','third') and ... order by case when state='first' then checked_at else null end, case when state='second' then ..., case when state='third' then...
Если правильный добавите — не сломается. Короче, тут 2 варианта, как минимум (просто общие идеи, не проверял — первый проще / оптимальнее, скорее всего): WITH t(state, planned_at, checked_at, is_first, forward_at, runned_at, runner_id) AS ( VALUES ('first', '2020-10-15'::date, '2020-01-02'::date, true, '2020-01-02'::date, '2020-01-02'::date, '94f08576-6c0f-4836-bbd0-66487d006e03') ), cte AS ( SELECT * FROM t WHERE state = 'first' and planned_at::DATE = current_date UNION ALL SELECT * FROM t WHERE state = 'second' and planned_at::DATE = current_date UNION ALL SELECT * FROM t WHERE state = 'third' and planned_at::DATE = current_date ) SELECT * FROM cte WHERE planned_at::DATE = current_date /* зачем это здесь, интересно? */ AND runner_id = '94f08576-6c0f-4836-bbd0-66487d006e03' ORDER BY state /* ну или добавить номер в каждое CTE */, CASE WHEN state = 'first' THEN checked_at END, CASE WHEN state = 'second' THEN is_first END DESC, CASE WHEN state = 'second' THEN forward_at END, CASE WHEN state = 'third' THEN runned_at END; ----------------- или так ------------- WITH t(state, planned_at, checked_at, is_first, forward_at, runned_at, runner_id) AS ( VALUES ('first', '2020-10-15'::date, '2020-01-02'::date, true, '2020-01-02'::date, '2020-01-02'::date, '94f08576-6c0f-4836-bbd0-66487d006e03') ), cte AS ( SELECT 1 AS cn, ROW_NUMBER() OVER (ORDER BY checked_at) AS rn, * FROM t WHERE state = 'first' and planned_at::DATE = current_date UNION ALL SELECT 2 AS cn, ROW_NUMBER() OVER (ORDER BY is_first DESC, forward_at) AS rn, * FROM t WHERE state = 'second' and planned_at::DATE = current_date UNION ALL SELECT 3 AS cn, ROW_NUMBER() OVER (ORDER BY runned_at) AS rn, * FROM t WHERE state = 'third' and planned_at::DATE = current_date ) SELECT * FROM cte WHERE planned_at::DATE = current_date AND runner_id = '94f08576-6c0f-4836-bbd0-66487d006e03' ORDER BY cn, rn;
С SELECT 1 AS cn, ROW_NUMBER() OVER (ORDER BY checked_at) AS rn, - работает. А я просто, без ROW_NUMBER() функции делал. 😂
там оба примера у Ярослава рабочие.
второй сейчас проверяю :) Спасибо
Обсуждают сегодня