Добавьте номер строки на основе предоставленной последовательности значений.

SELECT Code, Value FROM dbo.Sample

Выход:

 Code     Value
 Alpha    Pig
 Beta     Horse
 Charlie  Dog
 Delta    Cat
 Echo     Fish

Я хочу добавить столбец последовательности, указав список кодов и отсортировав список на основе порядка, указанного в предложении IN.

SELECT Code, Value FROM dbo.Sample
WHERE Code in ('Beta', 'Echo', 'Alpha')

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

Суть в том, что я хочу добавить номер строки в том порядке, в котором я их указываю.

Выход:

 Row   Code    Value
  1    Beta    Horse
  2    Echo    Fish
  3    Alpha   Pig

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

DECLARE @CodeList TABLE (Seq int, Code nchar(3))
DECLARE @CodeSequence varchar(255)
DECLARE @ThisCode char(3)
DECLARE @Codes int
SET @Codes = 0

-- string of comma-separated codes
SET @CodeSequence = 'ZZZ,ABC,FGH,YYY,BBB,CCC'

----loop through and create index and populate @CodeList
WHILE @Codes*4 < LEN(@CodeSequence)
BEGIN
    SET @ThisCode = SUBSTRING(@CodeSequence,@Codes*4+1,3)
    SET @Codes = @Codes + 1
    INSERT @CodeList (Seq, Code) VALUES (@Codes, @ThisCode)
END

SELECT Seq, Code from @CodeList

person kevro    schedule 02.03.2013    source источник
comment
этот выбор не обязательно будет производить эти значения в этом порядке без ORDER BY   -  person Mitch Wheat    schedule 02.03.2013


Ответы (5)


Вот только два способа, которые я видел, работают точно:

Первый использует CHARINDEX (аналогично Гордону, но я думаю, что оператор WHERE более точен, используя IN):

SELECT *
FROM Sample
WHERE Code IN ('Beta','Echo','Alpha')
ORDER BY CHARINDEX(Code+',','Beta,Echo,Alpha,')

Объединение запятой с кодом должно гарантировать, что подсовпадения не повлияют на результаты.

В качестве альтернативы вы можете использовать оператор CASE:

SELECT *
FROM Sample
WHERE Code in ('Beta','Echo','Alpha')
ORDER BY CASE 
  WHEN Code = 'Beta' THEN 1
  WHEN Code = 'Echo' THEN 2
  WHEN Code = 'Alpha' THEN 3
END

Демонстрация скрипки SQL

Обновленная демонстрация с частичными совпадениями.

person sgeddes    schedule 02.03.2013
comment
Я должен был указать, что все поля кода состоят из трех символов и уникальны, поскольку я вижу, как это может изменить результаты. Может быть, есть еще более короткий способ сделать это? - person kevro; 04.03.2013

Также вы можете использовать значения в качестве источника таблицы.

SELECT Row, Code, Value
FROM [Sample] s JOIN (       
                      SELECT ROW_NUMBER() OVER(ORDER BY(SELECT 1)) AS Row, Match
                      FROM (VALUES ('Beta'), 
                                   ('Echo'), 
                                   ('Alpha'))
                      x (Match)                             
                      ) o ON s.Code = o.Match
ORDER BY Row   

Демонстрация SQLFiddle

person Aleksandr Fedorenko    schedule 02.03.2013
comment
ORDER BY(SELECT 1) можно заменить на ORDER BY 1 (а еще лучше ORDER BY 42) - person a_horse_with_no_name; 02.03.2013
comment
@ a_horse_with_no_name спасибо, но когда я заменил на ORDER BY 1, это дало мне ошибку 5308: оконные функции не поддерживают целочисленные индексы в качестве выражений предложения ORDER BY. - person Aleksandr Fedorenko; 02.03.2013
comment
Интересно. Я не знал, что SQL Server не поддерживает это (для меня это звучит как ошибка, поскольку стандарт SQL в любом случае не разрешает ссылку на столбец по положению в этом месте). Видимо сортировка по константе вообще не допускается (order by null тоже не принимается). - person a_horse_with_no_name; 02.03.2013

Вот решение для любого длинного списка кодов. Создайте таблицу с самоувеличивающимся полем и кодом. Вставить в заданном порядке. Присоединяйтесь к столу и заказывайте по...

Некоторые детали. Прочтите это. Вы найдете там функцию, которая создает таблицу с полем автоинкремента из строки (разделенной запятыми), т.е.

mysql> call insertEngineer('dinusha,nuwan,nirosh');
Query OK, 1 row affected (0.12 sec)

mysql> select * from engineer;
+----+----------+
| ID | NAME     |
+----+----------+
|  1 | dinusha  |
|  2 | nuwan    |
|  3 | nirosh   |
+----+----------+

Затем присоединитесь к таблице Sample с результатом выше. ГЛ

person www    schedule 02.03.2013
comment
Мне нравится эта идея, но, возможно, вы могли бы предоставить пример кода, включая динамическое заполнение временной таблицы или табличной переменной, чтобы порядок мог меняться. - person gmm; 02.03.2013
comment
Я собираюсь попробовать этот. Мне нравится простота указания полей данных, так как я планирую менять поля и упорядочивать их во время тестирования. Спасибо. И я думаю, что изменю функцию, чтобы использовать разделитель-запятую, чтобы упростить ее еще больше. - person kevro; 04.03.2013
comment
Нет. Вы столкнулись с какими-либо проблемами? - person www; 04.03.2013
comment
SQL Server не поддерживает SUBSTRING_INDEX(). - person kevro; 05.03.2013
comment
Внизу темы есть эквивалент sql-server-performance.com/forum/threads/ - person www; 05.03.2013

Небольшое изменение того, что было сделано выше, чтобы также включить номера строк.

SELECT  CASE   
          WHEN Code = 'BetaBeta' THEN 1  
          WHEN Code = 'Beta' THEN 2  
          WHEN Code = 'Alpha' THEN 3  
        END CodeOrder,  
        *  
FROM Sample  
WHERE Code in ('BetaBeta','Beta','Alpha')  
ORDER BY CodeOrder  

Демонстрация скрипки SQL

person Praveen Nambiar    schedule 02.03.2013

У меня может возникнуть соблазн сделать это с помощью строковых функций:

declare @list varchar(8000) = 'Beta,Echo,Alpha';

with Sample as (
    select 'Alpha' as Code, 'Pig' as Value union all
    select 'Beta', 'Horse' union all
    select 'Charlie', 'Dog' union all
    select 'Delta', 'Cat' union all
    select 'Echo', 'Fish'
)
select * from Sample
where charindex(Code, @list) > 0
order by charindex(Code, @list)

Если вы беспокоитесь о подсовпадениях, просто выполните трюк с «разделителем»:

where @list like '%,'+Code+',%' 
person Gordon Linoff    schedule 02.03.2013
comment
работает до тех пор, пока слова в списке слов не имеют подсовпадений. например не будет работать «бета, эхо, бета-бета, альфа», но умная техника. - person Mitch Wheat; 02.03.2013
comment
Да, это очень умно и должно работать при условии, что нет возможных подсовпадений, как упоминал @MitchWheat. Хорошо сделано. - person gmm; 02.03.2013