sql ЗАМОВИТИ ЗА КРИЛИМИ значеннями в певному порядку?


94

Гаразд У мене є таблиця з індексованим ключем та неіндексованим полем. Мені потрібно знайти всі записи з певним значенням і повернути рядок. Я хотів би знати, чи можу я замовити кілька значень.

Приклад:

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

Синтаксис дійсний, але коли я виконую запит, він ніколи не повертає результатів, навіть якщо я обмежую його 1 записом. Чи є інший спосіб зробити це?

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

Що я не можу зробити:

  • GROUP BY, оскільки мені потрібно повернути конкретні значення записів
  • ДЕ x_field IN ('f', 'p', 'i', 'a'), мені потрібні всі значення, оскільки я намагаюся використовувати один запит для декількох тестів перевірки. І значення x_field не в порядку DESC / ASC

Після написання цього питання я починаю думати, що мені потрібно переосмислити це, LOL!


Може, натомість профспілка? Побудуйте окремі запити в тому порядку, в якому потрібно повернути результати, а потім об’єднайте ці запити?
kinakuta

Відповіді:


181
...
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

Ви можете використовувати ЛІВУ СПІЛКУ з "ЗНАЧЕННЯМИ ('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, так і false <true. Я би очікував, що це спрацює.
Ендрю Лазар,

7
Так, це працює подія в Postgres. Примітка до цього рішення полягає в тому, що ви отримуєте результат, відсортований у зворотному порядку. Отже, ви повинні помістити поля в зворотному порядку: ЗАМОВИТИ за 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

10

Я знайшов набагато більш чисте рішення для цього:

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-statement:

  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

Для когось, хто вперше замовляє замовлення за допомогою 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.