2016-06-13 5 views
1

Was ich:abrufen Sortiert Spalte Wert in SQL Server

Ich habe eine Spalte

ID  SerialNo 
1  101 
2  102 
3  103 
4  104 
5  105 
6  116 
7  117 
8  118 
9  119 
10 120 

Dies sind nur die 10 Dummy-Reihen. Die tatsächliche Tabelle hat über 100 000 Zeilen.

Was ich zu bekommen:

Verfahren oder Formel wie jede Sortiertechnik, die mir die Start- und End-Element [SerialNo] Spalte für jede Unterreihe zurückkehren konnte. Zum Beispiel

Erwartetes Ergebnis: 101-105, 115-120

Das Komma Trennung in dem obigen Ergebnis ist nicht wichtig, nur die Start- und End-Elemente sind wichtig.

Was habe ich versucht:

Ich habe es von PL/SQL-Programmierung, durch eine Schleife ausgeführt wird, in dem ich den Start bekommen und endend Elemente in einer Tabelle gespeichert zu werden. Aber wegen nein. von Zeilen (über 100 000) dauert die Abfrageausführung ungefähr 2 Minuten.

Ich habe auch über einige Sortiermethoden für den SQL Server gesucht, aber ich habe nichts gefunden. Da das Rendern jeder Zeile die doppelte Zeit in Anspruch nimmt, wird ein Sortieralgorithmus verwendet.

+0

Was ist der Bereich, um Unterserien zu definieren? – Swapnil

+0

Suchen Sie nach Lücken und Inseln http://StackOverflow.com/Questions/Tagged/Gaps-and-Islands – adrianm

+0

Warum sollte Ihr zweiter Bereich 115-120 und nicht 116-120 sein? –

Antwort

0

einfach den Anfang und das Ende jeder Serie zu finden, ist ganz einfach:

declare @t table (ID int not null, SerialNo int not null) 
insert into @t(ID,SerialNo) values 
(1 ,101), (2 ,102), (3 ,103), 
(4 ,104), (5 ,105), (6 ,116), 
(7 ,117), (8 ,118), (9 ,119), 
(10,120) 

;With Starts as (
    select t1.SerialNo,ROW_NUMBER() OVER (ORDER BY t1.SerialNo) as rn 
    from 
     @t t1 
      left join 
     @t t1_no 
      on t1.SerialNo = t1_no.SerialNo + 1 
    where t1_no.ID is null 
), Ends as (
    select t1.SerialNo,ROW_NUMBER() OVER (ORDER BY t1.SerialNo) as rn 
    from 
     @t t1 
      left join 
     @t t1_no 
      on t1.SerialNo = t1_no.SerialNo - 1 
    where t1_no.ID is null 
) 
select 
    s.SerialNo as StartSerial, 
    e.SerialNo as EndSerial 
from 
    Starts s 
     inner join 
    Ends e 
     on s.rn = e.rn 

Die Logik ist, dass ein Start eine Reihe ist, wo es keine Zeile ist, dass die SerialNo eins kleiner als die aktuelle hat Zeile, und eine End ist eine Zeile, in der es keine Zeile gibt, die SerialNo einen mehr als die aktuelle Zeile hat.

Dies kann immer noch schlecht funktionieren, wenn kein Index für die Spalte SerialNo vorhanden ist.

Ergebnisse:

StartSerial EndSerial 
----------- ----------- 
101   105 
116   120 

die hoffentlich akzeptabel ist, da Sie nicht wie zu kümmern schien, was sehen die spezifischen Ergebnisse. Es hält auch die Dinge fest.

+0

Arbeitete für mich ..! Danke @damien_the_unbeliever –

1

Angenommen, jede Unterserie sollte 5 Datensätze enthalten, wurde das Ergebnis unter Verwendung von sql erwartet. Ich hoffe das hilft.

DECLARE @subSeriesRange INT=5; 

CREATE TABLE #Temp(ID INT,SerialNo INT); 

INSERT INTO #Temp VALUES(1,101), 
(2,102), 
(3,103), 
(4,104), 
(5,105), 
(6,116), 
(7,117), 
(8,115), 
(9,119), 
(10,120); 

SELECT STUFF((SELECT CONCAT(CASE ID%@subSeriesRange WHEN 1 THEN ',' ELSE '-' END,SerialNo) 
     FROM #Temp 
     WHERE ID%@subSeriesRange = 1 OR ID%@subSeriesRange=0 
     ORDER BY ID 
     FOR XML PATH('')),1,1,'' 
     ); 

DROP TABLE #Temp; 
+0

Angesichts der Abwesenheit von "Sub-Serie" Definition funktioniert Ihre Antwort. – Alex

+0

der Bereich hier für Unterserien könnte jeder sein .... in Hunderten in Tausend @Alex thnx –

+0

Hallo @Priyank, Variable subSeriesRange hinzugefügt, um den Bereich zu definieren. – Swapnil