Come raggruppare i valori a distanza utilizzando SQL Server
-
19-08-2019 - |
Domanda
Ho una tabella di valori come questa
978412, 400
978813, 20
978834, 50
981001, 20
Come puoi vedere il secondo numero quando aggiunto al primo è 1 numero prima del successivo nella sequenza. L'ultimo numero non è compreso nell'intervallo (non segue una sequenza diretta, come nel valore successivo). Quello di cui ho bisogno è un CTE (sì, idealmente) che produrrà questo
978412, 472
981001, 20
La prima riga contiene il numero iniziale dell'intervallo quindi la somma dei nodi all'interno. La riga successiva è l'intervallo successivo che in questo esempio è uguale ai dati originali.
Soluzione
Dall'articolo pubblicato da Josh, ecco la mia opinione (testata e funzionante):
SELECT
MAX(t1.gapID) as gapID,
t2.gapID-MAX(t1.gapID)+t2.gapSize as gapSize
-- max(t1) is the specific lower bound of t2 because of the group by.
FROM
( -- t1 is the lower boundary of an island.
SELECT gapID
FROM gaps tbl1
WHERE
NOT EXISTS(
SELECT *
FROM gaps tbl2
WHERE tbl1.gapID = tbl2.gapID + tbl2.gapSize + 1
)
) t1
INNER JOIN ( -- t2 is the upper boundary of an island.
SELECT gapID, gapSize
FROM gaps tbl1
WHERE
NOT EXISTS(
SELECT * FROM gaps tbl2
WHERE tbl2.gapID = tbl1.gapID + tbl1.gapSize + 1
)
) t2 ON t1.gapID <= t2.gapID -- For all t1, we get all bigger t2 and opposite.
GROUP BY t2.gapID, t2.gapSize
Altri suggerimenti
Dai un'occhiata a questo Articolo MSDN . Ti dà una soluzione al tuo problema, se funzionerà per te dipende dalla quantità di dati che hai e dai tuoi requisiti di prestazione per la query.
Modifica:
Bene usando l'esempio nella query e andando con la sua ultima soluzione il secondo modo per ottenere isole (il primo modo ha provocato un errore su SQL 2005).
SELECT MIN(start) AS startGroup, endGroup, (endgroup-min(start) +1) as NumNodes
FROM (SELECT g1.gapID AS start,
(SELECT min(g2.gapID) FROM #gaps g2
WHERE g2.gapID >= g1.gapID and NOT EXISTS
(SELECT * FROM #gaps g3
WHERE g3.gapID - g2.gapID = 1)) as endGroup
FROM #gaps g1) T1 GROUP BY endGroup
La cosa che ho aggiunto è (endgroup-min (inizio) +1) come NumNodes
. Questo ti darà i conteggi.