sequenze continue in SQL
Domanda
Avere una tabella con i seguenti campi:
Ordine, Gruppo, Sequenza
è necessario che tutti gli ordini di un determinato gruppo formano una sequenza continua. Per esempio: 1,2,3,4 o 4,5,6,7. Come posso controllare utilizzando una singola query SQL quali ordini non rispettano questa regola? Grazie.
Example data:
Order Group Sequence
1 1 3
2 1 4
3 1 5
4 1 6
5 2 3
6 2 4
7 2 6
Expected result:
Order
5
6
7
accettato anche se la query restituisce solo il gruppo che ha la sequenza sbagliata, 2 per i dati di esempio.
Soluzione
Supponendo che le sequenze sono generati e quindi non può essere duplicato:
SELECT group
FROM theTable
GROUP BY group
HAVING MAX(Sequence) - MIN(Sequence) <> (COUNT(*) - 1);
Altri suggerimenti
Che ne dici di questo?
selezionare Gruppo dalla tabella
gruppo da
Group
avendo count (Sequenza) <= max (Sequenza) -min (Sequenza)
[Modifica] Questo presuppone che Sequenza non consente duplicati all'interno di un gruppo particolare. Potrebbe essere meglio utilizzare:!
count = max - min + 1
[Modifica di nuovo] D'oh, ancora non perfetta. Un'altra query per scovare i duplicati si sarebbe preso cura di questo però.
[Modifica l'ultimo] La query originale ha funzionato bene in SQLite, che è quello che avevo a disposizione per un test rapido. E 'molto più indulgenti che server SQL. Grazie alla campana per il puntatore.
Personalmente penso che vorrei prendere in considerazione ripensare il requisito. E 'la natura di database relazionali che le lacune nelle sequenze possono facilmente verificarsi a causa di record che vengono annullate. Per esempio, un ordine supppose inizia a creare quattro elementi in essa, ma non riesce per qualche Rason e viene eseguito il rollback. Se le sequenze precalcolate manualmente, si dovrebbe quindi avere un divario è quello rollback non è l'ultimo. In altri scenari, si potrebbe ottenere un gap dovuto a più utenti alla ricerca di valori di sequenza più o meno nello stesso tempo, o se all'ultimo minuto un cliente elimina un record dalla fine. Cosa stai onestamente cercando di guadagnare da avere sequenze contigue che non si ottiene da una relazione genitore-figlio?
Questa SQL seleziona gli ordini 3 e 4 hanno goduto nessuna continuo sequenze.
DECLARE @Orders TABLE ([Order] INTEGER, [Group] INTEGER, Sequence INTEGER)
INSERT INTO @Orders VALUES (1, 1, 0)
INSERT INTO @Orders VALUES (1, 2, 0)
INSERT INTO @Orders VALUES (1, 3, 0)
INSERT INTO @Orders VALUES (2, 4, 0)
INSERT INTO @Orders VALUES (2, 5, 0)
INSERT INTO @Orders VALUES (2, 6, 0)
INSERT INTO @Orders VALUES (3, 4, 0)
INSERT INTO @Orders VALUES (3, 6, 0)
INSERT INTO @Orders VALUES (4, 1, 0)
INSERT INTO @Orders VALUES (4, 2, 0)
INSERT INTO @Orders VALUES (4, 8, 0)
SELECT o1.[Order]
FROM @Orders o1
LEFT OUTER JOIN @Orders o2 ON o2.[Order] = o1.[Order] AND o2.[Group] = o1.[Group] + 1
WHERE o2.[Order] IS NULL
GROUP BY o1.[Order]
HAVING COUNT(*) > 1
Così il vostro tavolo è in forma di
Order Group Sequence
1 1 4
1 1 5
1 1 7
.. e si vuole scoprire che 1,1,6 manca?
Con
select
min(Sequence) MinSequence,
max(Seqence) MaxSequence
from
Orders
group by
[Order],
[Group]
è possibile scoprire i limiti per un determinato Ordine e Gruppo.
Ora è possibile simulare i dati corretti, utilizzando un apposito tavolo numeri , che ha appena contiene ogni singolo numero che si possa usare per una sequenza. Qui è un buon esempio di tale tabella di numeri. Non è importante come lo si crea, si potrebbe anche creare un file Excel con tutti i numeri da X a Y e l'importazione che eccellono foglio.
Nel mio esempio presumo tale tabella numeri chiamati "Numbers" con una sola colonna "n":
select
[Order],
[Group],
n Sequence
from
(select min(Sequence) MinSequence, max(Seqence) MaxSequence from [Table] group by [Order], [Group]) MinMaxSequence
left join Numbers on n >= MinSequence and n <= MaxSequence
Metti che SQL in una nuova vista. Nel mio esempio, io chiamerò la vista "vwCorrectOrders".
Questo ti dà i dati in cui le sequenze sono continui. Ora è possibile unire i dati con i dati originali per scoprire quali sequenze mancanti:
select
correctOrders.*
from
vwCorrectOrders co
left join Orders o on
co.[Order] = o.[Order]
and co.[Group] = o.[Group]
and co.Sequence = o.Sequence
where
o.Sequence is null
dovrebbe darvi
Order Group Sequence
1 1 6
Dopo un po 'mi si avvicinò con la seguente soluzione. Sembra funzionare, ma è altamente inefficiente. Si prega di aggiungere eventuali proposte di miglioramento.
SELECT OrdMain.Order
FROM ((Orders AS OrdMain
LEFT OUTER JOIN Orders AS OrdPrev ON (OrdPrev.Group = OrdMain.Group) AND (OrdPrev.Sequence = OrdMain.Sequence - 1))
LEFT OUTER JOIN Orders AS OrdNext ON (OrdNext.Group = OrdMain.Group) AND (OrdNext.Sequence = OrdMain.Sequence + 1))
WHERE ((OrdMain.Sequence < (SELECT MAX(Sequence) FROM Orders OrdMax WHERE (OrdMax.Group = OrdMain.Group))) AND (OrdNext.Order IS NULL)) OR
((OrdMain.Sequence > (SELECT MIN(Sequence) FROM Orders OrdMin WHERE (OrdMin.Group = OrdMain.Group))) AND (OrdPrev.Order IS NULL))