sql ORDER BY несколько значений в определенном порядке?


99

Хорошо, у меня есть таблица с индексированным ключом и неиндексированным полем. Мне нужно найти все записи с определенным значением и вернуть строку. Я хотел бы знать, могу ли я заказать по нескольким значениям.

Пример:

id     x_field
--     -----
123    a
124    a
125    a
126    b
127    f
128    b
129    a
130    x
131    x
132    b
133    p
134    p
135    i

псевдо: хотел бы, чтобы результаты были упорядочены следующим образом, where ORDER BY x_field = 'f', 'p', 'i', 'a'

SELECT *
FROM table
WHERE id NOT IN (126)
ORDER BY x_field 'f', 'p', 'i', 'a'

Итак, результаты будут такими:

id     x_field
--     -----
127    f
133    p
134    p
135    i
123    a
124    a
125    a
129    a

Синтаксис действителен, но когда я выполняю запрос, он никогда не возвращает никаких результатов, даже если я ограничиваю его одной записью. Есть ли другой способ сделать это?

Думайте о x_field как о результатах теста, и мне нужно проверить все записи, попадающие в это условие. Я хотел упорядочить результаты тестов по ошибочным значениям, пройденным значениям. Поэтому я мог сначала проверить ошибочные значения, а затем переданные значения, используя ORDER BY.

Что я не могу сделать:

  • GROUP BY, так как мне нужно вернуть определенные значения записи
  • WHERE x_field IN ('f', 'p', 'i', 'a'), мне нужны все значения, поскольку я пытаюсь использовать один запрос для нескольких проверочных тестов. И значения x_field не в порядке DESC / ASC

Написав этот вопрос, я начинаю думать, что мне нужно переосмыслить это, LOL!


Может, вместо этого союз? Создавать отдельные запросы в том порядке, в котором вы хотите, чтобы результаты возвращались, а затем выполнять объединение этих запросов?
kinakuta

Ответы:


189
...
WHERE
   x_field IN ('f', 'p', 'i', 'a') ...
ORDER BY
   CASE x_field
      WHEN 'f' THEN 1
      WHEN 'p' THEN 2
      WHEN 'i' THEN 3
      WHEN 'a' THEN 4
      ELSE 5 --needed only is no IN clause above. eg when = 'b'
   END, id

29

Вы можете использовать LEFT JOIN с «VALUES ('f', 1), ('p', 2), ('a', 3), ('i', 4)» и использовать второй столбец в вашем заказе -по выражению. Postgres будет использовать хеш-соединение, которое будет намного быстрее, чем огромный CASE, если у вас много значений. И это легче автогенерировать.

Если эта информация для заказа фиксирована, она должна иметь свою собственную таблицу.


6
Это, безусловно, самое элегантное решение!
jnns

28

Пытаться:

ORDER BY x_field='F', x_field='P', x_field='A', x_field='I'

Вы были на правильном пути, но, поместив x_field только в значение F, остальные 3 рассматривались как константы и не сравнивались ни с чем в наборе данных.


Поддерживает ли Postgres неявное логическое значение? Если да, то как выполняется логическая сортировка?
gbn

Мне понравилось это решение, но оно больше ничего не вернуло.
Phill Pafford

@gbn, да и ложь <правда. Я ожидал, что это сработает.
Эндрю Лазарус

7
Да, это работает в Postgres. Обратите внимание на это решение: результат будет отсортирован в обратном порядке. Таким образом, вам нужно разместить поля в обратном порядке: ORDER BY x_field = 'A', x_field = 'I', x_field = 'P', x_field = 'F',
igo

16

Используйте caseпереключатель, чтобы перевести коды в числа, которые можно сортировать:

ORDER BY
  case x_field
  when 'f' then 1
  when 'p' then 2
  when 'i' then 3
  when 'a' then 4
  else 5
  end

11

Я нашел для этого гораздо более чистое решение:

ORDER BY array_position(ARRAY['f', 'p', 'i', 'a']::varchar[], x_field)

Примечание: для array_position требуется Postgres v9.5 или выше.


1
Важно отметить, что array_position () доступен только в Postgres v9.5 и новее, afaik.
bigsee

спасибо, гораздо предпочел это методам CASE. Работает также с целыми числами; array_position(ARRAY[1, 0]::integer[], x_field)
Пол Уотсон

7

CASEИ ORDER BYпредложения должны работать, но я собираюсь предложить лошадь другого цвета. Предполагая, что существует только разумное количество значений для x_fieldи вы уже знаете, что они из себя представляют, создайте перечислимый тип с F, P, A и I в качестве значений (плюс любые другие возможные значения). Перечисления будут отсортированы в порядке, указанном в их CREATEзаявлении. Кроме того, вы можете использовать значимые имена значений - вероятно, ваше настоящее приложение использует, и вы просто замаскировали их для конфиденциальности - без лишнего пространства, поскольку сохраняется только порядковый номер.


1

Вы можете заказать по выбранному столбцу или другим выражениям.

Вот пример того, как отсортировать по результату case-оператора:

  SELECT col1
       , col2
    FROM tbl_Bill
   WHERE col1 = 0
ORDER BY -- order by case-statement
    CASE WHEN tbl_Bill.IsGen = 0 THEN 0
         WHEN tbl_Bill.IsGen = 1 THEN 1
         ELSE 2 END

Результатом будет список, начинающийся со строк «IsGen = 0», за которыми следуют строки «IsGen = 1» и все остальные строки в конце.

В конце вы можете добавить дополнительные параметры заказа:

  SELECT col1
       , col2
    FROM tbl_Bill
   WHERE col1 = 0
ORDER BY -- order by case-statement
    CASE WHEN tbl_Bill.IsGen = 0 THEN 0
         WHEN tbl_Bill.IsGen = 1 THEN 1
         ELSE 2 END,
         col1,
         col2

Хотя этот фрагмент кода может решить проблему, он не объясняет, почему и как он отвечает на вопрос. Пожалуйста, включите объяснение вашего кода , так как это действительно помогает улучшить качество вашего сообщения. Помните, что вы отвечаете на вопрос читателей в будущем, и эти люди могут не знать причин вашего предложения кода.
Самуэль Филипп

0

Для тех, кто плохо знаком с ORDER BY с CASE, это может быть полезно

ORDER BY 
    CASE WHEN GRADE = 'A' THEN 0
         WHEN GRADE = 'B' THEN 1
         ELSE 2 END

-2

вы можете использовать позицию (текст в тексте), чтобы упорядочить последовательность

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.