Нужен запрос postgresql, который возвращает нулевые значения после ненулевого значения

#ruby-on-rails #postgresql #sql-order-by

#ruby-on-rails #postgresql #sql-order-by

Вопрос:

Нужен запрос postgresql, который возвращает нулевое значение в конце ненулевого значения независимо от порядка возрастания / убывания.

Например: — У меня есть столбец с надписью purchase_price, имеющий значения 1, 5, 3, 0, null, null

Затем для ORDER BY purchase_price ASC он должен вернуть

 0
1
3
5
null
null
  

и для ORDER BY purchase_price DESC он должен возвращать

 5
3
1
0
null
null
  

Мне нужно обобщающее решение, которое я могу применить для 'boolean' , 'float' , 'string' 'integer' , 'date' типа данных

Ответ №1:

order by поддерживает nulls first/last . По умолчанию asc получает nulls last и desc получает nulls first . Вы можете переопределить их для каждого столбца:

 order by col1 desc nulls last, col2 desc nulls first, etc
  

Дополнительное примечание по этому поводу: основная причина заключается в том, что null помещаются в конец индекса btree. В PostgreSQL 9.0 order by col desc nulls last оптимизирован для разделения проверки индекса на две части (обратная проверка по ненулевым строкам, за которыми следуют нулевые строки). Это было не так в исходной версии, где это было добавлено (8.4, если не изменяет память); последняя продолжает выполнять последовательное сканирование всей таблицы с последующей быстрой сортировкой). А более старые версии вообще не поддерживают эту функцию. Так что будьте осторожны при использовании его во всем, кроме последних версий PostgreSQL.

Комментарии:

1. Спасибо Денису: — это работает gr8………. спасибо за объяснение, вы сэкономили мне пару часов…….

Ответ №2:

 select * from (select * from foo where x is not null order by x desc) a union all select  * from foo where x is null;
  

Дешевый взлом, но вы можете выбрать ненулевые случаи в любом порядке, который вы хотите, а затем выполнить ОБЪЕДИНЕНИЕ ALL (здесь важно all) с нулевыми случаями, которое будет строго следовать впоследствии.

Ответ №3:

Я всегда делал это с помощью скрытого объединения в следующих строках:

 select *, '1' as orderCol
from table
where nullableColumn is not null
union
select *, '2' as orderCol
from table
where nullableColumn is null
order by orderCol, nullableColumn 
  

Вам явно нужно изменить его для упорядочивания desc — например, установив значения наоборот…

Довольно общий, но не очень элегантный.

Комментарии:

1. Использование union вместо union all предотвращает возврат повторяющихся строк, даже если в исходной таблице были повторяющиеся строки.