2015-05-19 2 views
5

У меня есть данные, как этотSQL сортировать по номеру содержится как подстроки

Name  SortOrder 
------------------- 
Lower 1  3 
Lower 10  2 
Lower 2  1 
Lower 1%  6 
Lower 1.5% 5 
Lower 3%  4 
Average  7 
Upper 1  10 
Upper 10  8 
Upper 1%  12 
Upper 1.5% 11 
Average  10 /* sorted 
Average Poor 11 * alphabetically 
Rich   12 * only */ 
Min_Low10  17 
Min_Low20  18 
Min_Low30  19 
Min_Up10  20 
Min_Up20  21 
Min_Up30  22 

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

Name  SortOrder 
------------------- 
Lower 3%  1 
Lower 1.5% 2 
Lower 1%  3 
Lower 10  4 
Lower 2  5 
Lower 1  6 
Min_Low30  7 
Min_Low20  8 
Min_Low10  9 
Average  10 /* sorted 
Average Poor 11 * alphabetically 
Rich   12 * only */ 
Min_Up10  13 
Min_Up20  14 
Min_Up30  15 
Upper 1  16 
Upper 2  17 
Upper 10  18 
Upper 1%  19 
Upper 1.5% 20 

т.е. те подгруппы с числами должны либо сортироваться по восходящей, либо нисходящей (в зависимости от того, что ее нижняя или верхняя) и что-либо еще без числового числа должны быть просто отсортированы в алфавитном порядке и помещены между ними.

Я думаю, что у меня есть группа по первым символам каждой подгруппы, а затем преобразуйте числовое число и порядок. Но это дает мне сообщение об ошибке при попытке преобразовать его: Error converting data type varchar to numeric.

SELECT * 
    ,RowNum = 
    CASE 
     WHEN Name LIKE 'Lower %[%]' THEN 
      ROW_NUMBER() over (partition by SUBSTRING(Name,1,5) ORDER By CAST(SUBSTRING(Name,7,LEN(Name)-3) as decimal) DESC) 
     WHEN Name LIKE 'Lower %' THEN 
      ROW_NUMBER() over (partition by SUBSTRING(Name,1,5) ORDER By SUBSTRING(Name,7,LEN(Name)) DESC) 
     WHEN Name LIKE 'Upper %[%]' THEN 
      (ROW_NUMBER() over (partition by SUBSTRING(Name,1,5) ORDER By SUBSTRING(Name,7,LEN(Name)-3))) 
     WHEN Name LIKE 'Upper %' THEN 
      (ROW_NUMBER() over (partition by SUBSTRING(Name,1,5) ORDER By SUBSTRING(Name,7,LEN(Name)))) 

     ELSE -1 
    END 
    FROM Table1 
    ORDER BY RowNum 

вот sqlfiddle

Edit: измененные значения данных, поскольку они включают в себя: 1, а также 10, который будет неправильно отсортированы, если они являются varchars.

+0

Вы можете выбрать 'SUBSTRING (имя, 7, LEN (Имя) -3)' и посмотреть, что это дает? Я предполагаю, что это не «десятичный». – NickyvV

+0

Нет, это варчар. вот почему я хочу отдать его десятичному значению – user3710760

+0

Я знаю это, но что делает 'SELECT SUBSTRING (Name, 7, LEN (Name) -3) FROM Table1 WHERE Name LIKE 'Lower% [%]'' return? – NickyvV

ответ

1

Вы можете попробовать это:

select * 
    , RowNum = 
    ROW_NUMBER() over (order by 
     case 
      when Name LIKE 'Lower %[%]' then 1 
      when Name LIKE 'Lower %' then 2 
      when Name LIKE 'Min_Low%' then 3 
      when Name LIKE 'Min_Up%' then 5 
      when Name LIKE 'Upper %[%]' then 7 
      when Name LIKE 'Upper %' then 6 
      else 4 
     end 
     , convert(numeric(6,2), case 
      when Name LIKE 'Lower %[%]' then replace(replace(Name, 'Lower ',''),'%', '') 
      when Name LIKE 'Lower %' then replace(Name, 'Lower ','') 
      when Name LIKE 'Min_Low%' then replace(Name, 'Min_Low','') 
     end) desc 
     , convert(numeric(6,2), case 
      when Name LIKE 'Min_Up%' then replace(Name, 'Min_Up','') 
      when Name LIKE 'Upper %[%]' then replace(replace(Name, 'Upper ',''),'%', '') 
      when Name LIKE 'Upper %' then replace(Name, 'Upper ','') 
     end) 
     , Name 
    ) 
from #Table1 

ОБНОВЛЕНИЕ

Ее е оператор обновления:

update #Table1 set SortOrder = t2.RowNum 
from #Table1 t1 
    join (
select * 
    , RowNum = 
    ROW_NUMBER() over (order by 
     case 
      when Name LIKE 'Lower %[%]' then 1 
      when Name LIKE 'Lower %' then 2 
      when Name LIKE 'Min_Low%' then 3 
      when Name LIKE 'Min_Up%' then 5 
      when Name LIKE 'Upper %[%]' then 7 
      when Name LIKE 'Upper %' then 6 
      else 4 
     end 
     , convert(numeric(6,2), case 
      when Name LIKE 'Lower %[%]' then replace(replace(Name, 'Lower ',''),'%', '') 
      when Name LIKE 'Lower %' then replace(Name, 'Lower ','') 
      when Name LIKE 'Min_Low%' then replace(Name, 'Min_Low','') 
     end) desc 
     , convert(numeric(6,2), case 
      when Name LIKE 'Min_Up%' then replace(Name, 'Min_Up','') 
      when Name LIKE 'Upper %[%]' then replace(replace(Name, 'Upper ',''),'%', '') 
      when Name LIKE 'Upper %' then replace(Name, 'Upper ','') 
     end) 
     , Name 
    ) 
from #Table1) t2 on t1.Name=t2.Name 
+0

Спасибо, это работает для вывода, но как бы я обновил столбец SortOrder, который будет установлен в RowNum? – user3710760

+0

Спасибо, обновление почти сработало. Это должно быть 't1.Name = t2.Name' в конце, хотя. – user3710760

+0

Я обновил ваш код. – user3710760

1

Ниже база ВЫБРАТЬ можно использовать для обновления вашей таблицы или непосредственно, чтобы получить результаты

Исправлены проблемы с помощью:

SELECT Name, ROW_NUMBER() over (ORDER By RowNumber) SortOrder 
FROM (
SELECT TOP 100 PERCENT Name, ROW_NUMBER() over (ORDER By RowName, Value DESC) RowNumber 
FROM (SELECT TOP 100 PERCENT Name,RowName = CASE 
     WHEN Name LIKE 'Lower %[%]%' THEN 'LowerP' 
     WHEN Name LIKE 'Lower %' THEN 'LowerS' 
     WHEN Name LIKE 'Min_Low%' THEN 'LowerX' 
     ELSE 'LowerZ' + Name 
    END, Value = CASE 
     WHEN Name LIKE 'Lower %[%]%' THEN CONVERT(float, SUBSTRING(Name, 6, LEN(Name)-6)) 
     WHEN Name LIKE 'Lower %' THEN CONVERT(float, SUBSTRING(Name, 6, 10)) 
     WHEN Name LIKE 'Min_Low%' THEN CONVERT(float, SUBSTRING(Name, 8, 10)) 
     ELSE 100 
     END 
    FROM Sorting 
    WHERE Name NOT LIKE '%Up%' 
    ORDER BY RowName, Value DESC) a 
UNION 
SELECT TOP 100 PERCENT Name, ROW_NUMBER() over (ORDER By RowName, Value ASC) + 1000 RowNumber 
FROM (
    SELECT TOP 100 PERCENT Name,RowName = CASE 
     WHEN Name LIKE 'Min_Up%' THEN 'UpperA' 
     WHEN Name LIKE 'Upper %' AND NOT SUBSTRING(Name, LEN(Name), 1) = '%' THEN 'UpperB' 
     WHEN SUBSTRING(Name, LEN(Name), 1) = '%' THEN 'UpperC' 
     ELSE 'Middle' 
    END, Value = CASE 
     WHEN Name LIKE 'Upper %[%]%' THEN CONVERT(float, SUBSTRING(Name, 6, LEN(Name)-6)) 
     WHEN Name LIKE 'Upper %' THEN CONVERT(float, SUBSTRING(Name, 6, 10)) 
     WHEN Name LIKE 'Min_Up%' THEN CONVERT(float, SUBSTRING(Name, 7, 10)) 
     ELSE 100 
     END 
FROM Sorting 
WHERE Name LIKE '%Up%' 
ORDER BY RowName, Value ASC) b 
ORDER BY RowNumber) c 
+0

Это выглядит отлично, за исключением записей в середине, не отсортированы в алфавитном порядке – user3710760

+0

Я просто понял, что он не работает для моего фактического набора данных, который имеет нижний 3, а также меньше 30%, они будут отсортированы неправильно. Я обновил исходное сообщение – user3710760

+0

Добавлена ​​новая версия для устранения проблем – Simone

0

Немного уплотняется версия:

SELECT Name 
FROM (SELECT Name, SUBSTRING(Name, PATINDEX('%[0-9]%', Name), LEN(Name) 
            - PATINDEX('%[0-9]%', Name) 
            - PATINDEX('%[0-9]%', REVERSE(Name)) + 2) n FROM @t) t 
ORDER BY ROW_NUMBER() OVER 
(ORDER BY CASE WHEN Name LIKE 'lower %[%]' THEN 1 
       WHEN Name LIKE 'lower %' THEN 2 
       WHEN Name LIKE 'min_low%' THEN 3 
       WHEN Name LIKE 'min_up%' THEN 5 
       WHEN Name LIKE 'upper %[%]' THEN 7 
       WHEN Name LIKE 'upper %' THEN 6 
       ELSE 4 END, 
      CASE WHEN Name LIKE 'lower%' OR Name LIKE 'min_low%' 
       THEN CAST(n AS DECIMAL(10, 2)) END DESC, 
      CASE WHEN Name LIKE 'upper%' OR Name LIKE 'min_up%' 
       THEN CAST(n AS DECIMAL(10, 2)) END, 
      Name) 
Смежные вопросы