2009-05-18 21 views
1

eine Tabelle mit den folgenden Feldern zu haben:kontinuierliche Sequenzen in SQL

Ordnung, Gruppe, Sequenz

ist es erforderlich, dass alle Aufträge in einer bestimmten Gruppe eine kontinuierliche Folge bilden. Zum Beispiel: 1,2,3,4 oder 4,5,6,7. Wie kann ich mit einer einzigen SQL-Abfrage prüfen, welche Aufträge nicht dieser Regel entsprechen? Vielen Dank.

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 

akzeptiert auch, wenn die Abfrage nur die Gruppe gibt, die die falsche Sequenzdaten, 2 für die Beispiel hat.

+0

welche sql db verwenden Sie. in oracle könnte man das mit den ranking funktionen machen ... –

+0

Microsoft Access :) – Tihauan

+0

Die Antworten stimmen nicht zu In welcher Spalte die 1,2,3,4 Daten stehen, vielleicht kann man das mit einigen Beispielen verdeutlichen. – Andomar

Antwort

4

Unter der Annahme, dass die Sequenzen erzeugt werden und daher nicht kopiert werden kann:

 

SELECT group 
FROM theTable 
GROUP BY group 
HAVING MAX(Sequence) - MIN(Sequence) <> (COUNT(*) - 1); 
 
+0

Nice one, vermisse die = in der wo aber – Andomar

+0

Danke, Flucht kann ein Schmerz sein. – Bell

2

Wie wäre es damit?

wählen Gruppe aus Tabelle
Gruppe für Gruppe
mit count (Sequence) < = max (Sequence) -min (Sequenz)

[Edit] Dies setzt voraus, dass Sequenz keine Duplikate innerhalb einer bestimmten Gruppe erlauben, . Es könnte besser sein zu verwenden:
count! = Max - min + 1

[Bearbeiten Sie wieder] D'oh, immer noch nicht perfekt. Eine andere Abfrage, um Duplikate auszuspülen, würde dies jedoch berücksichtigen.

[Bearbeiten Sie die letzte] Die ursprüngliche Abfrage funktionierte gut in sqlite, die ich für einen schnellen Test zur Verfügung hatte. Es ist viel verzeihender als SQL Server. Danke an Bell für den Zeiger.

+0

Was ist mit Duplikaten? –

+0

Ich würde erwarten, dass dies zu geben und Fehler in Bezug auf die Spalte "Sequenz" muss Teil einer GROUP BY oder eine Aggregatfunktion sein. Welcher der Werte der Sequenz für die Gruppe, die das Problem hat, soll es zurückgeben? – Bell

1

Dieses SQL wählt die Ordnungen 3 und 4 aus, die keine kontinuierlichen Folgen haben.

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 
0

So Tisch ist in Form von

Order Group Sequence 
1  1  4 
1  1  5 
1  1  7 

..und Sie wollen herausfinden, dass 1,1,6 fehlt?

Mit

select 
    min(Sequence) MinSequence, 
    max(Seqence) MaxSequence 
from 
    Orders 
group by 
    [Order], 
    [Group] 

können Sie die Grenzen für eine bestimmte Ordnung und Gruppen erfahren.

Jetzt können Sie die korrekten Daten simulieren, indem Sie eine spezielle Nummerentabelle verwenden, die nur jede einzelne Zahl enthält, die Sie für eine Sequenz verwenden könnten. Here ist ein gutes Beispiel für eine solche Zahlentabelle. Es ist nicht wichtig, wie Sie es erstellen, Sie können auch eine Excel-Datei mit allen Zahlen von x bis y erstellen und dieses Excel-Blatt importieren.

In meinem Beispiel nehme ich an, eine solche Zahlen Tabelle "Numbers" mit nur einer Spalte "n" genannt:

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 

Put, die in eine neue Ansicht SQL. In meinem Beispiel werde ich die Ansicht "vwCorrectOrders" aufrufen.

Dies gibt Ihnen die Daten, wo die Sequenzen kontinuierlich sind.Jetzt können Sie verbinden, dass die Daten mit den Originaldaten, um herauszufinden, welche Sequenzen fehlen:

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 

geben Sollten Sie

Order Group Sequence 
1  1  6 
0

Nach einer Weile habe ich mit der folgenden Lösung kam. Es scheint zu funktionieren, aber es ist sehr ineffizient. Bitte fügen Sie Verbesserungsvorschläge hinzu.

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)) 
+0

Vielleicht lesen Sie die anderen Antworten, bevor Sie schreiben;) – Andomar

+0

Es ist ein weit verbreitetes Missverständnis, dass Unterabfragen einmal für jede Zeile ausgewertet werden. Jedes DBMS, das es wert ist, implementiert eine typische Unterabfrage mit speziellen Joins oder mit spezifischen Optimierungen. Unterabfragen sind ein zentrales Konzept in SQL, und die meisten Anbieter haben viel Zeit in die Verbesserung ihrer Leistung investiert, basierend auf dem Umfang akademischer Forschung zu diesem Thema. Um ehrlich zu sein, kann ich nicht speziell für die JET-Maschine sprechen, aber ich verstehe, dass sie in den letzten Jahren ziemlich viel Arbeit gemacht hat. Das heißt nicht, dass Ihre Antwort weniger effizient ist - nur Unterabfragen sind nicht so schlecht. – WCWedin

2

Persönlich denke ich, ich würde überdenken, die Anforderung zu überdenken. Es liegt in der Natur von relationalen Datenbanken, dass Lücken in Sequenzen leicht auftreten können, weil Datensätze zurückgerollt werden. Zum Beispiel, suppompose eine Reihenfolge beginnt vier Objekte zu erstellen, aber eine für einige rason fehlschlägt und wird zurückgesetzt. Wenn du die Sequenzen manuell vorberechnet hast, hättest du dann eine Lücke, wenn die zurückgewürfelte nicht die letzte ist. In anderen Szenarios entsteht möglicherweise eine Lücke, da mehrere Benutzer ungefähr zur gleichen Zeit nach Sequenzwerten suchen oder wenn ein Kunde in der letzten Minute einen Datensatz aus der Bestellung gelöscht hat. Was wollen Sie wirklich davon haben, zusammenhängende Sequenzen zu haben, die Sie nicht aus einer Eltern-Kind-Beziehung bekommen?