Как внедрить двойную сортировку в SQL запросе?

tolst

Новичок
Как внедрить двойную сортировку в SQL запросе?

В обсчем есть база:

id | date_start | picked_date
----------------------------
1 | 1153145421 | 0
2 | 1153145422 | 0
3 | 1153145423 | 1153145429
4 | 1153145424 | 0
5 | 1153145425 | 1153145843

Задача:
Правильно отсартировать данные что бы соблюсти следующие требования:

1) Сначала должны идти записи с picked_date не равными нулю, и должны сортироваться от меньшего к большему (в обсчем то это и вызвало у меня затруднение, так как делая ORDER BY picked_date ASC сверху сначала появляются нули, а только потом правильно составленная сортировка)

2) Потом отсартированные данные должны сортироваться по второму полю: все у кого picked_date равняется нулю должны отсортировываться по date_start от большего к меньшему (тут затруднений нет)

Заранее благодарен за ответ.
 

zerkms

TDD infected
Команда форума
ORDER BY IF(`picked_date` = 0, 1, 0), `picked_date`, `otherfield`

только есть мнение что будет немного накладно эту сортировку делать

ps: слово то какое - "внедрить" ;)
 

tolst

Новичок
а если использовать UNION? мне на другом форуме вот это посоветовали:

select id,date_start, picked_date, 1 from table
where picked_date <> 0
union
select id,date_start, picked_date, 2 from table
where picked_date = 0
order by 4,3,2


только мне тут не понятно что такое order by 4,3,2 (наверное я тут сам должен подставить нужную мне сортировку)
 

zerkms

TDD infected
Команда форума
4 3 2 - это поля, по которым идёт сортировка
соответсвенно константа 2, picked_date, date_start
 

Wicked

Новичок
[оффъ]
мне больше понравилось слово "отсартировать" :)
[/оффъ]

и когда станет накладно, можно будет прибегнуть к кэшированию IF(`picked_date` = 0, 1, 0) в каком-нибудь поле, по которому, к тому же, сделать индекс. Ну и IF(`picked_date` = 0, 1, 0) я бы заменил на простое булевское `picked_date` = 0
 

tolst

Новичок
2zerkms спасибо за подсказку о полях по которым идет сортировка

Решено, спасибо большое.... вот решение:
SELECT id, datepost, pickedstart, 1
FROM table
WHERE pickedstart <>0
UNION
SELECT id, datepost, pickedstart, 2
FROM table
WHERE pickedstart =0
ORDER BY 4 ASC , 3 ASC , 2 DESC
 

Wicked

Новичок
я бы сделал примерно так:
(
SELECT id, datepost, pickedstart
FROM table
WHERE pickedstart <>0
order by pickedstart asc, datepost desc
) union all (
SELECT id, datepost, pickedstart
FROM table
WHERE pickedstart =0
order by datepost desc
)

доводы:
1) union all не будет пытаться откидывать повторяющиеся записи. Простой union вероятно не будет знать, что таких и так нету.
2) union у нас и так будет выдавать сначала ненулевые записи, а потом нулевые, так что order by 4 - лишний.
3) в каждом селекте остается неизбыточная сортировка с возможностью использовать индексы.

в ман лезть лень, так что пробуй :) доверяй, но проверяй.
 
Сверху