Custom ORDER BY Пояснение - PullRequest
       4

Custom ORDER BY Пояснение

53 голосов
/ 03 ноября 2010

Я нашел это некоторое время назад и с тех пор пользуюсь им;Однако, глядя на это сегодня, я понял, что не до конца понимаю, почему это работает.Может кто-нибудь пролить свет на это для меня?

ORDER BY  s.type!= 'Nails',
          s.type!= 'Bolts',
          s.type!= 'Washers',
          s.type!= 'Screws',
          s.type!= 'Staples',
          s.type!= 'Nuts', ...

Если я заказываю по s.type, он упорядочивается по алфавиту.Если я использую приведенный выше пример, он использует тот же порядок, что и позиции строк.Чего я не понимаю, так это использования! =.Если я использую =, это появляется в обратном порядке.Я не могу обернуть голову вокруг концепции этого.

Мне бы пришло в голову, что использование = вместо вышеуказанного! = Поставило бы Nails первым в позицию, но это не так.последний.Наверное, мой вопрос таков: почему я должен использовать! =, А не = в этой ситуации?

Ответы [ 4 ]

51 голосов
/ 03 ноября 2010

Каждое выражение оценивается как bool и обрабатывается как 0 для false и 1 для true и сортируется соответствующим образом Даже при том, что это работает, логике трудно следовать (и таким образом поддерживать). Я использую функцию, которая находит индекс значения в массиве.

ORDER BY idx(array['Nails','Bolts','Washers','Screws','Staples','Nuts'], s.type)

За этим намного легче следовать. Гвозди будут отсортированы первыми, а орехи - последними. Вы можете увидеть, как создать функцию idx в репозитории Postgres snippets. http://wiki.postgresql.org/wiki/Array_Index

36 голосов
/ 03 ноября 2010

Я никогда не видел этого, но, кажется, это имеет смысл.

Сначала он заказывает на s.type != 'Nails'. Это false для каждой строки, содержащей Nails в столбце type. После этого он сортируется по Bolts. Опять же для всех столбцов, которые содержат Bolts как type, это оценивается как ложное. И так далее.

Небольшой тест показывает, что 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
34 голосов
/ 29 декабря 2016

@ Скотт Бэйли предложил отличную идею.Но это может быть еще проще (вам не нужно создавать пользовательские функции), начиная с PostgreSQL 9.5.Просто используйте функцию array_position:

ORDER BY array_position(array['Nails','Bolts','Washers','Screws','Staples','Nuts'], s.type)
5 голосов
/ 12 сентября 2017

с array_position, он должен иметь тот же тип, к которому вы обращаетесь.

например:

select array_position(array['foo'::char,'bar','baz'::char], 'bar');
select array_position(array['foo'::char,'bar','baz'::char], 'baz'::char);
...