2008-12-30 5 views
0

J'ai une table dans laquelle une colonne contient des enregistrements en double mais d'autres colonnes sont distinctes. si quelque chose comme çaregroupement d'enregistrements dans une table temporaire

Code de statut

1234 version SubCode D1 1 A

1234 D1 0 P

1234 DA 1 A

1234 DB 1 P

5678 BB 1 A

5678 BB 0 P

5678 BP 1 A

5678 BJ 1 A

0987 HH 1 A

Ainsi, dans le tableau ci-dessus. le sous-code et la version sont des valeurs uniques alors que le code est répété. Je veux transférer des enregistrements de la table ci-dessus dans une table temporaire. Seuls les enregistrements que je voudrais transférer sont où tous les sous-codes d'un code ont le statut «A» et je ne les veux dans la table temporaire qu'une seule fois.

Donc, à partir de l'exemple ci-dessus. la table temporaire ne doit avoir que 5678 et 0987 puisque tous les sous-codes relatifs à 5678 ont le statut 'A' et tous les sous-codes pour 0987 (ils en ont seulement un) ont le statut A. 1234 est omis parce que son sous-code 'DB' a un statut de 'P'

J'apprécierais n'importe quelle aide!

Répondre

-1
INSERT theTempTable (Code) 
SELECT t.Code 
FROM theTable t 
     LEFT OUTER JOIN theTable subT ON (t.Code = subT.Code AND subT.status <> 'A') 
WHERE subT.Code IS NULL 
GROUP BY t.Code 

Cela devrait faire l'affaire. La logique est un peu compliquée, mais je ferai de mon mieux pour expliquer comment elle est dérivée.

La jointure externe combinée à la vérification IS NULL vous permet de rechercher l'absence d'un critère. Combinez cela avec l'inverse de ce que vous recherchez normalement (dans ce cas, status = 'A') et la requête réussit quand il n'y a pas de lignes qui ne correspondent pas. C'est la même chose que ((il n'y a pas de lignes) OU (toutes les lignes correspondent)). Puisque nous savons qu'il y a des lignes dues à l'autre requête sur la table, toutes les lignes doivent correspondre.

+0

Cela ne renvoie pas les résultats corrects. 5678 sera exclu car au moins une ligne existe avec un statut non "A". –

0

Dans votre sélection, ajoutez une clause where qui lit:

Select [stuff] 
From Table T 
Where Exists 
    (Select * From Table 
    Where Code = T.Code 
     And Status = 'A') 
    And Not Exists 
    (Select * From Table I 
    Where Code = T.Code 
     And Not Exists 
      (Select * From Table 
      Where Code = I.Code 
       And SubCode = I.SubCode 
       And Status = 'A')) 

En anglais, Montrez-moi les lignes, où il y a au moins une ligne avec le statut « A », et il n'y a pas lignes avec une sous-code spécifique, qui ne pas au moins une ligne avec ce code/sous-code, avec le statut « A »

+0

Cela ne renvoie pas les résultats corrects. 5678 sera exclu car au moins une ligne existe avec un statut non "A". (aussi, votre requête a SubCode où je pense que vous vouliez dire le statut) –

+0

Oui thx, corrigé que –

+0

Cela ne fonctionne toujours pas. –

1

On ne sait pas très bien si la colonne de version entre en jeu ou non. Par exemple, voulez-vous seulement considérer les lignes avec la plus grande version ou si n'importe quel sous-élément a un "A" devrait-il compter. Prenez 5678, BB par exemple, où la version 1 a un "A" et la version 0 a un "B". Est-ce que 5678 est inclus parce qu'au moins un sous-code BB a un "A" ou est-ce parce que la version 1 a un "A".

Le code suivant suppose que vous voulez tous les codes où chaque sous-code a au moins un "A" indépendamment de la version.

SELECT 
    T1.code, 
    T1.subcode, 
    T1.version, 
    T1.status 
FROM 
    MyTable T1 
WHERE 
    (
     SELECT COUNT(DISTINCT subcode) 
     FROM MyTable T2 
     WHERE T2.code = T1.code 
    ) = 
    (
     SELECT COUNT(DISTINCT subcode) 
     FROM MyTable T3 
     WHERE T3.code = T1.code AND T3.status = 'A' 
    ) 

Les performances peuvent être abyssales si votre table est grande. Je vais essayer de trouver une requête qui est susceptible d'avoir de meilleures performances, car c'était hors de ma tête.

En outre, si vous expliquez toute l'étendue de votre problème, nous pouvons peut-être trouver un moyen de se débarrasser de cette table temp ...;)

Voici deux méthodes plus possibles. Encore beaucoup de sous-requêtes, mais elles ont l'air d'être plus performantes que la méthode ci-dessus. Ils sont tous les deux très similaires, bien que le second ait un meilleur plan de requête dans ma base de données. Bien sûr, avec des données limitées et aucune indexation, ce n'est pas un bon test. Vous devriez essayer toutes les méthodes et voir ce qui est le mieux pour votre base de données.

SELECT 
    T1.code, 
    T1.subcode, 
    T1.version, 
    T1.status 
FROM 
    MyTable T1 
WHERE 
    EXISTS 
    (
     SELECT * 
     FROM MyTable T2 
     WHERE T2.code = T1.code 
      AND T2.status = 'A' 
    ) AND 
    NOT EXISTS 
    (
     SELECT * 
     FROM MyTable T3 
     LEFT OUTER JOIN MyTable T4 ON 
      T4.code = T3.code AND 
      T4.subcode = T3.subcode AND 
      T4.status = 'A' 
     WHERE T3.code = T1.code 
      AND T3.status <> 'A' 
      AND T4.code IS NULL 
    ) 

SELECT 
    T1.code, 
    T1.subcode, 
    T1.version, 
    T1.status 
FROM 
    MyTable T1 
WHERE 
    EXISTS 
    (
     SELECT * 
     FROM MyTable T2 
     WHERE T2.code = T1.code 
      AND T2.status = 'A' 
    ) AND 
    NOT EXISTS 
    (
     SELECT * 
     FROM MyTable T3 
     WHERE T3.code = T1.code 
      AND T3.status <> 'A' 
      AND NOT EXISTS 
      (
       SELECT * 
       FROM MyTable T4 
       WHERE T4.code = T3.code 
        AND T4.subcode = T3.subcode 
        AND T4.status = 'A' 
      ) 
    ) 
+0

Bonne solution. FROM est l'ennemi de la performance, mais vous le savez. –

1

Voici ma solution

SELECT Code 
FROM 
(
    SELECT 
    Code, 
    COUNT(SubCode) as SubCodeCount 
    SUM(CASE WHEN ACount > 0 THEN 1 ELSE 0 END) 
     as SubCodeCountWithA 
    FROM 
    (
    SELECT 
     Code, 
     SubCode, 
     SUM(CASE WHEN Status = 'A' THEN 1 ELSE 0 END) 
     as ACount 
    FROM CodeTable 
    GROUP BY Code, SubCode 
) sub 
    GROUP BY Code 
) sub2 
WHERE SubCodeCountWithA = SubCodeCount 

Brisons vers le bas de l'intérieur.

SELECT 
     Code, 
     SubCode, 
     SUM(CASE WHEN Status = 'A' THEN 1 ELSE 0 END) 
     as ACount 
    FROM CodeTable 
    GROUP BY Code, SubCode 

Groupez les codes et les sous-codes (chaque ligne est un appariement distinct de code et de sous-code). Voyez combien de A sont apparus dans chaque paire.

SELECT 
    Code, 
    COUNT(SubCode) as SubCodeCount 
    SUM(CASE WHEN ACount > 0 THEN 1 ELSE 0 END) 
     as SubCodeCountWithA 
    FROM 
    --previous 
    GROUP BY Code 

Regrouper ces appariements par code (maintenant chaque ligne est un code) et comptez combien de souscodes il y a, et combien de sous-codes avaient un A.

SELECT Code 
FROM 
    --previous 
WHERE SubCodeCountWithA = SubCodeCount 

Émettre ces codes avec la même nombre de sous-codes en tant que sous-codes avec A.

+0

Aussi une solution intéressante. Sur l'ensemble de données limité ci-dessus sur une table sans index, je vois un coût élevé pour le tri (relativement), mais avec une table réelle avec des données, cela peut être meilleur que les analyses de table de ma méthode. –

Questions connexes