Мне интересно, есть ли (возможно, лучший способ) упорядочить по порядку значений в предложении IN ().
Проблема в том, что у меня есть 2 запроса: один получает все идентификаторы, а второй - всю информацию. Первый создает порядок идентификаторов, по которому я хочу, чтобы второй был упорядочен. Идентификаторы помещаются в предложение IN () в правильном порядке.
Так что это будет что-то вроде (очень упрощенно):
SELECT id FROM table1 WHERE ... ORDER BY display_order, name
SELECT name, description, ... WHERE id IN ([id's from first])
Проблема в том, что второй запрос не возвращает результаты в том же порядке, в котором идентификаторы помещены в предложение IN ().
Одно решение, которое я нашел, - это поместить все идентификаторы во временную таблицу с автоматически увеличивающимся полем, которое затем присоединяется ко второму запросу.
Есть вариант лучше?
Примечание: Поскольку первый запрос выполняется «пользователем», а второй - в фоновом процессе, невозможно объединить запрос 2 в 1 с помощью подзапросов.
Я использую MySQL, но думаю, было бы полезно, чтобы он отметил, какие варианты есть и для других БД.






Попробуйте это:
SELECT name, description, ...
WHERE id IN
(SELECT id FROM table1 WHERE...)
ORDER BY
(SELECT display_order FROM table1 WHERE...),
(SELECT name FROM table1 WHERE...)
WHERE, вероятно, потребует небольшой настройки, чтобы коррелированные подзапросы работали правильно, но основной принцип должен быть здравым.
Используйте функцию MySQL FIELD():
SELECT name, description, ...
FROM ...
WHERE id IN([ids, any order])
ORDER BY FIELD(id, [ids in order])
FIELD() вернет индекс первого параметра, который равен первому параметру (кроме самого первого параметра).
FIELD('a', 'a', 'b', 'c')
вернет 1
FIELD('a', 'c', 'b', 'a')
вернет 3
Это сделает именно то, что вы хотите, если вы вставите идентификаторы в предложение IN() и функцию FIELD() в одном и том же порядке.
Сортировка @Vojto в произвольном порядке по определению выполняется медленно. Это делает все возможное, поскольку нет гарантии, что параметры IN и FIELD равны. Выполнение этого в программном коде может быть быстрее, если использовать эти дополнительные знания. Конечно, было бы разумнее возложить эту нагрузку на клиента, а не на сервер, если вы имеете в виду производительность сервера.
что насчет sqlite?
Мне нужно посмотреть следующий ответ, чтобы он заработал, не могу понять ваш синтаксис, я пытался использовать [], затем (), и в этом нет необходимости, просто идентификаторы, разделенные запятыми.
На ум приходят два решения:
order by case id when 123 then 1 when 456 then 2 else null end asc
order by instr(','||id||',',',123,456,') asc
(instr() от Oracle; возможно, у вас есть locate() или charindex() или что-то в этом роде)
Для MySQL также можно использовать FIELD_IN_SET (): dev.mysql.com/doc/refman/5.0/en/…
Моей первой мыслью было написать один запрос, но вы сказали, что это невозможно, потому что один выполняется пользователем, а другой - в фоновом режиме. Как вы храните список идентификаторов для передачи от пользователя фоновому процессу? Почему бы не поместить их во временную таблицу со столбцом для обозначения порядка.
Так как насчет этого:
Предложение IN описывает набор значений, а наборы не имеют порядка.
Ваше решение с объединением и последующим упорядочиванием в столбце display_order является наиболее правильным решением; все остальное, вероятно, является взломом, связанным с СУБД (или что-то делает с функциями OLAP в стандартном SQL). Конечно, объединение - это наиболее переносимое решение (хотя создание данных со значениями display_order может быть проблематичным). Обратите внимание, что вам может потребоваться выбрать столбцы упорядочивания; раньше это было требованием в стандартном SQL, хотя я считаю, что некоторое время назад оно, как правило, было смягчено (возможно, так же давно, как SQL-92).
Используйте функцию MySQL FIND_IN_SET:
SELECT *
FROM table_name
WHERE id IN (..,..,..,..)
ORDER BY FIND_IN_SET (coloumn_name, .., .., ..);
См. Ниже, как получить отсортированные данные.
SELECT ...
FROM ...
WHERE zip IN (91709,92886,92807,...,91356)
AND user.status=1
ORDER
BY provider.package_id DESC
, FIELD(zip,91709,92886,92807,...,91356)
LIMIT 10
Для Oracle работает решение Джона с использованием функции instr (). Вот немного другое решение, которое сработало -
SELECT id
FROM table1
WHERE id IN (1, 20, 45, 60)
ORDER BY instr('1, 20, 45, 60', id)
SELECT ORDER_NO, DELIVERY_ADDRESS
from IFSAPP.PURCHASE_ORDER_TAB
where ORDER_NO in ('52000077','52000079','52000167','52000297','52000204','52000409','52000126')
ORDER BY instr('52000077,52000079,52000167,52000297,52000204,52000409,52000126',ORDER_NO)
работал действительно отлично
У меня работал на Oracle. Быстро и просто. Спасибо.
Ответ на получение отсортированных данных.
SELECT ...
FROM ...
ORDER BY FIELD(user_id,5,3,2,...,50) LIMIT 10
Я думаю, вам следует сохранить свои данные таким образом, чтобы вы просто выполняли соединение, и оно было идеальным, поэтому никаких взломов и сложных вещей не происходило.
У меня, например, есть список идентификаторов треков «Недавно воспроизведенные», на SQLite я просто делаю:
SELECT * FROM recently NATURAL JOIN tracks;
О, если бы жизнь была такой простой :)
Если вы хотите выполнить произвольную сортировку запроса с использованием значений, введенных запросом в MS SQL Server 2008+, это можно сделать, создав таблицу на лету и выполнив подобное соединение (с использованием номенклатуры из OP).
SELECT table1.name, table1.description ...
FROM (VALUES (id1,1), (id2,2), (id3,3) ...) AS orderTbl(orderKey, orderIdx)
LEFT JOIN table1 ON orderTbl.orderKey=table1.id
ORDER BY orderTbl.orderIdx
Если вы замените оператор VALUES чем-то еще, что делает то же самое, но в ANSI SQL, то это должно работать с любой базой данных SQL.
Примечание: Второй столбец в созданной таблице (orderTbl.orderIdx) необходим при запросе наборов записей больше 100 или около того. Первоначально у меня не было столбца orderIdx, но я обнаружил, что с наборами результатов больше 100 мне приходилось явно сортировать по этому столбцу; в любом случае в SQL Server Express 2014.
Этот вопрос касается MySQL ... не уверен, что ваш запрос будет работать в MySQL.
@ Дэррил, это не так. Но этот пост становится одним из лучших результатов, когда вы гуглите, как заказывать с помощью предложения IN, поэтому я решил, что могу опубликовать его здесь, и общая методология применяется ко всем ANSI-совместимым SQL-серверам (просто замените оператор VALUES стандартным способ создания таблицы).
Обратите внимание, у меня это сработало, но только после того, как я заменил ссылки на orderTbl.orderKey, orderTbl.orderIndex на orderKey, orderIndex
Я просто пытался сделать это на MS SQL Server, где у нас нет FIELD ():
SELECT table1.id
...
INNER JOIN
(VALUES (10,1),(3,2),(4,3),(5,4),(7,5),(8,6),(9,7),(2,8),(6,9),(5,10)
) AS X(id,sortorder)
ON X.id = table1.id
ORDER BY X.sortorder
Обратите внимание, что я тоже разрешаю дублирование.
см. примечание, а также, как указано, примеры запросов чрезвычайно упрощены, поэтому я не могу объединить их в один запрос с подзапросами.