Сохранять порядок в разделе "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/," ");

Важно то, что я могу в своем сценарии кэшировать результат до следующего обновления связанных элементов, чтобы запрос выполнялся только при создании/изменении элемента, а не при просмотре каждого элемента, что помогало свести к минимуму любые производительность.