Сохранять порядок в разделе "IN"
Можно ли сохранить порядок из условного предложения "IN"?
Я нашел этот вопрос на SO, но в своем примере OP уже отсортировал предложение "IN".
Мой случай отличается, предложение "IN" в случайном порядке
Что-то вроде этого:
SELECT SomeField,OtherField
FROM TestResult
WHERE TestResult.SomeField IN (45,2,445,12,789)
Я хотел бы получить результаты в (45,2,445,12,789) порядке. Я использую базу данных Oracle. Может быть, есть атрибут в SQL, который я могу использовать с условным предложением, чтобы указать, чтобы сохранить порядок предложения.
Ответы
Ответ 1
Не будет надежного заказа, если вы не используете предложение ORDER BY.
SELECT SomeField,OtherField
FROM TestResult
WHERE TestResult.SomeField IN (45,2,445,12,789)
order by case TestResult.SomeField
when 45 then 1
when 2 then 2
when 445 then 3
...
end
Вы можете разделить запрос на 5 запросов union all'd вместе, хотя...
SELECT SomeField,OtherField
FROM TestResult
WHERE TestResult.SomeField = 4
union all
SELECT SomeField,OtherField
FROM TestResult
WHERE TestResult.SomeField = 2
union all
...
Я бы больше доверял предыдущему методу, и он, вероятно, будет работать намного лучше.
Ответ 2
Попробуйте следующее:
SELECT T.SomeField,T.OtherField
FROM TestResult T
JOIN
(
SELECT 1 as Id, 45 as Val FROM dual UNION ALL
SELECT 2, 2 FROM dual UNION ALL
SELECT 3, 445 FROM dual UNION ALL
SELECT 4, 12 FROM dual UNION ALL
SELECT 5, 789 FROM dual
) I
ON T.SomeField = I.Val
ORDER BY I.Id
Ответ 3
Существует альтернатива, которая использует строковые функции:
with const as (select ',45,2,445,12,789,' as vals)
select tr.*
from TestResult tr cross join const
where instr(const.vals, ','||cast(tr.somefield as varchar(255))||',') > 0
order by instr(const.vals, ','||cast(tr.somefield as varchar(255))||',')
Я предлагаю это, потому что вам может легче поддерживать строку значений, а не промежуточную таблицу.
Ответ 4
Я смог сделать это в своем приложении, используя (используя SQL Server 2016)
select ItemID, iName
from Items
where ItemID in (13,11,12,1)
order by CHARINDEX(' ' + Convert("varchar",ItemID) + ' ',' 13 , 11 , 12 , 1 ')
Я использовал код-код для замены \b
(граница слова) пробелом. Что-то вроде...
var mylist = "13,11,12,1";
var spacedlist = replace(mylist,/\b/," ");
Важно то, что я могу в своем сценарии кэшировать результат до следующего обновления связанных элементов, чтобы запрос выполнялся только при создании/изменении элемента, а не при просмотре каждого элемента, что помогало свести к минимуму любые производительность.