2015-05-19 13 views
5

Ho dati similiSQL ordina per numero contenuto come stringa

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 

voglio aggiornare i ordinamento in modo che quando sono in ordine, esso sarà come questo

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 

ie quei sottogruppi con una numerica dovrebbero essere ordinati in ordine ascendente o discendente (a seconda che sia inferiore o superiore) e qualsiasi altra cosa senza un valore numerico dovrebbe essere semplicemente ordinata alfabeticamente e inserita tra parentesi.

Penso di avere un gruppo per i primi caratteri di ogni sottogruppo, quindi convertire il numerico e l'ordine in base a quello. Ma mi dà un messaggio di errore quando si tenta di convertirlo: 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 

Ecco l'Edit sqlfiddle

: cambiato valori di dati in quanto includono 1 e 10, che sarebbe ordinato sbagliato se sono varchars.

+0

Puoi selezionare 'SOTTOSTRINGA (nome, 7, LEN (Nome) -3)' e vedere che cosa succede? Suppongo che non sia un decimale ... – NickyvV

+0

No, è un varchar. ecco perché voglio farlo in un decimale – user3710760

+0

Lo so, ma cosa significa 'SELEZIONARE SUBSTRING (Nome, 7, LEN (Nome) -3) DA Tabella1 WHERE Nome LIKE 'Lower% [%]'' return? – NickyvV

risposta

1

Si può provare questo:

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

Lei e è l'istruzione di aggiornamento:

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

Grazie, sembra funzionare per l'output, ma come dovrei aggiornare la colonna SortOrder per essere impostata su RowNum? – user3710760

+0

Grazie, l'aggiornamento ha funzionato quasi. Dovrebbe essere 't1.Name = t2.Name' alla fine però. – user3710760

+0

Ho aggiornato il tuo codice. – user3710760

1

Quello che segue è la base SELEZIONA è possibile utilizzare per l'aggiornamento il vostro tavolo o direttamente per ottenere risultati

risolto i problemi utilizzando:

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

Questo sembra buono, tranne che le voci nel mezzo non sono in ordine alfabetico – user3710760

+0

Ho appena realizzato che non funziona per il mio set di dati effettivo che ha inferiore 3 e inferiore del 30%, sarebbero ordinati in modo errato. Ho aggiornato il post originale – user3710760

+0

Aggiunta una nuova revisione per superare i problemi – Simone

0

Un po 'la versione compattata:

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) 
Problemi correlati