2009-05-18 7 views
1

Avoir une table avec les champs suivants:séquences continues dans SQL

Ordre, Groupe, Séquence

il est nécessaire que toutes les commandes dans un groupe donné forment une séquence continue. Par exemple: 1,2,3,4 ou 4,5,6,7. Comment puis-je vérifier en utilisant une seule requête SQL quelles commandes ne sont pas conformes à cette règle? Je vous remercie.

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 

Accepte également si la requête renvoie uniquement le groupe qui a la mauvaise séquence, 2 pour les données d'exemple.

+0

que sql db utilisez-vous. dans oracle son possible, vous pourriez le faire avec les fonctions de classement ... –

+0

Microsoft Access :) – Tihauan

+0

Les réponses ne sont pas d'accord Quelle colonne contient les données 1,2,3,4, peut-être vous pouvez clarifier avec quelques exemples. – Andomar

Répondre

4

En supposant que les séquences sont générées et ne peuvent donc pas être dupliqué:

 

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

Nice, manquant le = dans le où – Andomar

+0

Merci, s'échapper peut être une douleur. – Bell

2

Que pensez-vous de cela?

sélectionner Groupe du Tableau
groupe par groupe
comptage ayant (séquence) < = max (séquence) -min (séquence)

[Modifier] Cela suppose que la séquence ne permet pas de doublons dans un groupe particulier . Il pourrait être préférable d'utiliser:
count! = Max - min + 1

[Modifier encore] D'oh, toujours pas parfait. Une autre requête pour débusquer les doublons prendrait soin de cela. [Modifier le dernier] La requête d'origine a bien fonctionné dans sqlite, ce que j'avais à disposition pour un test rapide. C'est beaucoup plus tolérant que le serveur SQL. Merci à Bell pour le pointeur.

+0

qu'en est-il des doublons? –

+0

Je m'attendrais à ce que cela donne et erreur à l'effet de 'Colonne "Séquence" doit faire partie d'un GROUP BY ou une fonction d'agrégat ". Laquelle des valeurs de séquence pour le groupe qui a le problème est-elle censée revenir? – Bell

1

Ce SQL sélectionne les ordres 3 et 4 qui n'ont pas de séquences continues.

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

Ainsi, votre table est sous forme de

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

..et vous voulez savoir que 1,1,6 est manquant?

Avec

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

vous pouvez trouver les limites pour un ordre et groupe donné.

Maintenant, vous pouvez simuler les données correctes en utilisant un tableau spécial numéros, qui contient seulement tous les numéros que vous pourriez utiliser pour une séquence. Here est un bon exemple d'une telle table de nombres. Ce n'est pas important comment vous le créez, vous pouvez également créer un fichier Excel avec tous les nombres de x à y et importer cette feuille Excel.

Dans mon exemple, je suppose un tel tableau de nombres appelés « numéros » avec une seule colonne « 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 

Put que SQL dans une nouvelle vue. Dans mon exemple, je vais appeler la vue "vwCorrectOrders".

Ceci vous donne les données où les séquences sont continues.Maintenant, vous pouvez joindre ces données avec les données d'origine pour savoir quelles séquences manquent:

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 

devrait vous donner

Order Group Sequence 
1  1  6 
0

Après un certain temps je suis venu avec la solution suivante. Cela semble fonctionner mais c'est très inefficace. S'il vous plaît ajouter des suggestions d'amélioration.

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

Peut-être lire les autres réponses avant de poster;) – Andomar

+0

C'est une idée fausse commune que les sous-requêtes sont évaluées une fois pour chaque ligne. Tout SGBD digne de ce nom implémente une sous-requête typique en utilisant des jointures spéciales ou avec des optimisations spécifiques. Les sous-requêtes sont un concept central dans SQL, et la plupart des fournisseurs ont investi beaucoup de temps dans l'amélioration de leurs performances, sur la base de volumes de recherche académique sur le sujet. Pour être honnête, je ne peux pas parler en particulier du moteur JET, mais je comprends qu'il a fait pas mal de travail ces dernières années. Cela ne veut pas dire que je pense que votre réponse est moins efficace - juste que les sous-requêtes ne sont pas si mauvaises. – WCWedin

2

Personnellement, je pense que je considérerais repenser l'exigence. C'est la nature des bases de données relationnelles que les lacunes dans les séquences peuvent facilement se produire en raison des enregistrements qui sont annulés. Par exemple, supposons qu'un ordre commence à créer quatre éléments, mais un échoue pour certains rasons et est annulé. Si vous précalculez manuellement les séquences, vous aurez alors un écart qui n'est pas le dernier. Dans d'autres cas, vous risquez d'obtenir un écart dû à plusieurs utilisateurs qui recherchent des valeurs de séquence à peu près au même moment ou si, à la dernière minute, un client a supprimé un enregistrement de la commande. Qu'est-ce que vous cherchez honnêtement à gagner en ayant des séquences contiguës que vous n'obtenez pas d'une relation parent-enfant?

Questions connexes