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.

È stato utile?

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))
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top