2015-04-17 9 views
12

Ich habe eine Tabelle mit einem varchar Feld. Dieses Feld speichert hierarchische Nummern, die ich bestellen möchte. HierSortierung hierarchischen Textes in SQL

ist ein Beispiel für meine Daten:

1 
1.1 
1.1.1 
1.1.2 
1.1.3. 
1.1.4 
1.1.5 
1.1.6. 
1.1.7 
10. 
10.1 
10.2 
10.3 
11. 
11.1 
11.2 
2. 
2.1 
1.2.2 
1.2.2.1 
1.2.2.2 

Wie kann ich das folgende Ergebnis mit T-SQL erreichen:

1 
1.1 
1.1.1 
1.1.2 
1.1.3 
1.1.4 
1.1.5 
1.1.6 
1.1.7 
1.2.2 
1.2.2.1 
1.2.2.2 
2. 
2.1 
10. 
10.1 
10.2 
10.3 
11. 
11.1 
11.2 

Ich habe versucht, die Teile mit der folgenden SQL aufzuspalten, aber das ist nicht elegant.

SELECT CASE WHEN CHARINDEX('.',SUBSTRING(LTRIM(RTRIM(NR)),1,LEN(NR)-1)+REPLACE(SUBSTRING(LTRIM(RTRIM(NR)),LEN(NR),1),'.','')) = 0 
    THEN SUBSTRING(LTRIM(RTRIM(NR)),1,LEN(NR)-1)+REPLACE(SUBSTRING(LTRIM(RTRIM(NR)),LEN(NR),1),'.','') 
    ELSE REPLACE(SUBSTRING(SUBSTRING(LTRIM(RTRIM(NR)),1,LEN(NR)-1)+REPLACE(SUBSTRING(LTRIM(RTRIM(NR)),LEN(NR),1),'.',''),1, CHARINDEX('.',SUBSTRING(LTRIM(RTRIM(NR)),1,LEN(NR)-1)+REPLACE(SUBSTRING(LTRIM(RTRIM(NR)),LEN(NR),1),'.',''))),'.','') 
    END AS FIRST_PART 
,CASE WHEN CHARINDEX('.',SUBSTRING(LTRIM(RTRIM(NR)),1,LEN(NR)-1)+REPLACE(SUBSTRING(LTRIM(RTRIM(NR)),LEN(NR),1),'.','')) > 0 
     THEN SUBSTRING( 
SUBSTRING(LTRIM(RTRIM(NR)),1,LEN(NR)-1)+REPLACE(SUBSTRING(LTRIM(RTRIM(NR)),LEN(NR),1),'.','') 
    ,CHARINDEX('.',SUBSTRING(LTRIM(RTRIM(NR)),1,LEN(NR)-1)+REPLACE(SUBSTRING(LTRIM(RTRIM(NR)),LEN(NR),1),'.','')) +1 
    ,LEN(SUBSTRING(LTRIM(RTRIM(NR)),1,LEN(NR)-1)+REPLACE(SUBSTRING(LTRIM(RTRIM(NR)),LEN(NR),1),'.','') ) 
    ) 
    ELSE '0' 
    END AS SECOND_PART 
FROM TEST_TABLE 

Ist dies ein besserer Weg, dies zu tun?

+0

Speichern Sie Beziehungen statt statt. getrennte Elemente als Spaltenwerte? – jarlh

+0

kann ich nur durchführen, eine SELECT und haben keine Möglichkeit zum Speichern von Beziehungen – h0mebrewer

+2

http://stackoverflow.com/questions/6446000/properly-sorting-dotted-numbers-stored-as-character-in-sql-server – niyou

Antwort

6

Try this:

DECLARE @DataSource TABLE 
(
    [Value] VARCHAR(12) 
); 

INSERT INTO @DataSource ([Value]) 
VALUES ('1') 
     ,('1.1') 
     ,('1.1.1') 
     ,('1.1.2') 
     ,('1.1.3.') 
     ,('1.1.4') 
     ,('1.1.5') 
     ,('1.1.6.') 
     ,('1.1.7') 
     ,('10.') 
     ,('10.1') 
     ,('10.2') 
     ,('10.3') 
     ,('11.') 
     ,('11.1') 
     ,('11.2') 
     ,('2.') 
     ,('2.1') 
     ,('1.2.2') 
     ,('1.2.2.1') 
     ,('1.2.2.2'); 

SELECT * 
FROM @DataSource 
ORDER BY CAST('/' + IIF(RIGHT([Value],1) = '.', LEFT([Value], LEN([Value]) - 1), [Value]) + '/' AS HIERARCHYID); 

Sie die hierarchyid um weitere Informationen zu überprüfen. Die Überprüfung in der ORDER BY Klausel entfernt nur die . am Ende des Wertes (wenn solche vorhanden sind).


können Sie die IIF Funktion ändern, um dies mit einfachen CASE WHEN wie:

SELECT * 
FROM @DataSource 
ORDER BY CAST('/' + CASE WHEN RIGHT([Value],1) = '.' THEN LEFT([Value], LEN([Value]) - 1) ELSE [Value] END + '/' AS HIERARCHYID); 
+0

Funktioniert nur mit SQL Server 2012 und höher. IIF ist nicht verfügbar bei SQL Server 2008 – h0mebrewer

+0

@ h0mebrewer Sie können die 'IIF' mit' CASE WHEN' leicht ändern - überprüfen Sie die Bearbeitung. – gotqn

-1

entfernen Punkte und Bestellung:

select column from table order by replace(column,'.','') 

Und es gibt keine Notwendigkeit, varchar zu konvertieren, wenn Sie an die Nummer will, dass 10 vor 2 kommt.

+0

Ich möchte nicht 10 für 2. – h0mebrewer