Пользовательский ORDER BY Explanation
Я нашел это некоторое время назад и использовал его с тех пор; однако, глядя на него сегодня, я понял, что я не совсем понимаю, почему он работает. Может ли кто-то пролить свет на него для меня?
ORDER BY s.type!= 'Nails',
s.type!= 'Bolts',
s.type!= 'Washers',
s.type!= 'Screws',
s.type!= 'Staples',
s.type!= 'Nuts', ...
Если я заказываю по s.type, он упорядочивает по алфавиту. Если я использую пример выше, он использует тот же порядок, что и позиции строк. То, что я не понимаю, это использование! =. Если я использую =, он появляется в обратном порядке. Я не могу окунуться в концепцию этого.
Мне было бы разумно, что использование = вместо the!= выше поставило бы Nails на первое место, но это не так, оно помещает его в последнее. Я предполагаю, что мой вопрос таков: почему я должен использовать! =, Not = в этой ситуации?
Ответы
Ответ 1
Я никогда не видел его, но, похоже, имеет смысл.
Сначала он заказывает s.type != 'Nails'
. Это false
для каждой строки, содержащей Nails
в столбце type
. После этого он сортируется по Bolts
. Опять же для всех столбцов, которые содержат Bolts
как type
, это оценивается как false. И так далее.
Небольшой тест показывает, что false
упорядочен до true
. Итак, у вас есть следующее: сначала вы получаете все строки с Nails
сверху, потому что первый ORDER BY
, оцененный как false
и false
. Остальные строки сортируются по второму критерию ORDER BY
. И так далее.
type | != Nails | != Bolts | != Washers
'Nails' | false | true | true
'Bolts' | true | false | true
'Washers' | true | true | false
Ответ 2
Каждое выражение оценивается как bool и обрабатывается как 0 для false и 1 для true и сортируется соответствующим образом. Несмотря на то, что это работает, логика трудно следовать (и тем самым поддерживать). Я использую функцию, которая находит индекс значения в массиве.
ORDER BY idx(array['Nails','Bolts','Washers','Screws','Staples','Nuts'], s.type)
Это намного проще. Сначала гвозди будут отсортированы, а орехи отсортированы последними. Вы можете увидеть, как создать функцию idx в репозитории фрагментов Postgres.
http://wiki.postgresql.org/wiki/Array_Index
Ответ 3
@Scott Bailey предложил отличную идею. Но это может быть еще проще (вам не нужно создавать пользовательскую функцию), поскольку PostgreSQL 9.5. Просто используйте array_position
:
ORDER BY array_position(array['Nails','Bolts','Washers','Screws','Staples','Nuts'], s.type)
Ответ 4
с array_position, он должен иметь тот же тип, с которым вы запрашиваете.
например:
select array_position(array['foo'::char,'bar','baz'::char], 'bar');
select array_position(array['foo'::char,'bar','baz'::char], 'baz'::char);