Question

Des excuses préemptives pour les noms de table / colonne absurdes de ces requêtes. Si vous avez déjà travaillé avec le backend DB de Remedy, vous comprendrez.

J'ai un problème lorsqu'un membre distincte renvoie une valeur nulle, alors que je soupçonne que la valeur réelle devrait se situer quelque part dans les années 20 (23, je crois). Vous trouverez ci-dessous une série de requêtes et leurs valeurs de retour.

SELECT count(distinct t442.c1)
      FROM t442, t658, t631
     WHERE t442.c1 = t658.c536870930
       AND t442.c200000003 = 'Network'
       AND t442.c536871139 < 2
       AND t631.c536870913 = t442.c1
       AND t658.c536870925 = 1
       AND (t442.c7 = 6 OR t442.c7 = 5)
       AND t442.c536870954 > 1141300800
       AND (t442.c240000010 = 0)

Résultat = 497.

Ajoutez la table t649 et assurez-vous que les enregistrements sont liés à la table t442:

 SELECT COUNT (DISTINCT t442.c1)
              FROM t442, t658, t631, t649
             WHERE t442.c1 = t658.c536870930
               AND t442.c200000003 = 'Network'
               AND t442.c536871139 < 2
               AND t631.c536870913 = t442.c1
               AND t658.c536870925 = 1
               AND (t442.c7 = 6 OR t442.c7 = 5)
               AND t442.c536870954 > 1141300800
               AND (t442.c240000010 = 0)
               AND t442.c1 = t649.c536870914

Résultat = 263.

Filtrez les enregistrements de la table t649 où la colonne c536870939 < = 1:

.
SELECT COUNT (DISTINCT t442.c1)
          FROM t442, t658, t631, t649
         WHERE t442.c1 = t658.c536870930
           AND t442.c200000003 = 'Network'
           AND t442.c536871139 < 2
           AND t631.c536870913 = t442.c1
           AND t658.c536870925 = 1
           AND (t442.c7 = 6 OR t442.c7 = 5)
           AND t442.c536870954 > 1141300800
           AND (t442.c240000010 = 0)
           AND t442.c1 = t649.c536870914
           AND t649.c536870939 > 1

Résultat = 24.

Filtrez sur l'instruction HAVING:

SELECT COUNT (DISTINCT t442.c1)
          FROM t442, t658, t631, t649
         WHERE t442.c1 = t658.c536870930
           AND t442.c200000003 = 'Network'
           AND t442.c536871139 < 2
           AND t631.c536870913 = t442.c1
           AND t658.c536870925 = 1
           AND (t442.c7 = 6 OR t442.c7 = 5)
           AND t442.c536870954 > 1141300800
           AND (t442.c240000010 = 0)
           AND t442.c1 = t649.c536870914
           AND t649.c536870939 > 1
        HAVING COUNT (DISTINCT t631.c536870922) =
                                              COUNT (DISTINCT t649.c536870931)

Résultat = null.

Si j'exécute la requête suivante, je ne vois rien dans la liste des résultats qui explique pourquoi je ne reçois aucune sorte de valeur de retour. Cela est vrai même si je supprime le DISTINCT du SELECT. (Je récupère respectivement 25 et 4265 lignes de données).

SELECT DISTINCT t442.c1, t631.c536870922, t649.c536870931
          FROM t442, t658, t631, t649
         WHERE t442.c1 = t658.c536870930
           AND t442.c200000003 = 'Network'
           AND t442.c536871139 < 2
           AND t631.c536870913 = t442.c1
           AND t658.c536870925 = 1
           AND (t442.c7 = 6 OR t442.c7 = 5)
           AND t442.c536870954 > 1141300800
           AND (t442.c240000010 = 0)
           AND t442.c1 = t649.c536870914
           AND t649.c536870939 > 1

J'ai plusieurs autres endroits où la requête est configurée exactement comme celle qui renvoie la valeur NULL et fonctionne parfaitement - les nombres utilisables qui correspondent aux valeurs correctes. Je dois supposer que tout ce qui est unique dans cette situation est lié aux données et non à la requête, mais je ne suis pas sûr de ce qu'il faut rechercher dans les données pour l'expliquer. Je n'ai pas été en mesure de trouver des valeurs NULL dans les données brutes avant l'agrégation. Je ne sais pas quoi d'autre pourrait causer cela.

Toute aide serait appréciée.

Était-ce utile?

La solution

Je comprends maintenant. Votre problème dans la requête d'origine est qu'il est très inhabituel (sinon erroné) d'utiliser une clause HAVING sans une clause GROUP BY. La réponse réside dans l’ordre de fonctionnement des différentes parties de la requête.

Dans la requête d'origine, procédez comme suit:

SELECT COUNT(DISTINCT t442.c1)
  FROM ...
 WHERE ...
HAVING COUNT(DISTINCT t631.c536870922) = COUNT(DISTINCT t649.c536870931);

La base de données effectuera vos jointures et vos contraintes. Elle effectuera alors toutes les opérations de regroupement et d'agrégation. Dans ce cas, vous ne regroupez pas, les opérations COUNT concernent l'ensemble du jeu de données. Compte tenu des valeurs que vous avez publiées ci-dessus, COUNT (DISTINCT t631.c536870922) = 25 et COUNT (DISTINCT t649.c536870931) = 24. La clause HAVING est maintenant appliquée, ce qui ne correspond à rien - votre demande pour les cas où le nombre total set (même s’il existe plusieurs c1) sont égaux, et ils ne le sont pas. DISTINCT est appliqué à un jeu de résultats vide et vous n’obtenez rien.

Ce que vous voulez vraiment faire est simplement une version de ce que vous avez posté dans l'exemple qui crache le nombre de lignes:

SELECT count(*)
  FROM (SELECT t442.c1     
          FROM t442
             , t658
             , t631
             , t649
         WHERE t442.c1 = t658.c536870930
           AND t442.c200000003 = 'Network'
           AND t442.c536871139 < 2
           AND t631.c536870913 = t442.c1
           AND t658.c536870925 = 1
           AND (   t442.c7 = 6
                OR t442.c7 = 5)
           AND t442.c536870954 > 1141300800
           AND (t442.c240000010 = 0)
           AND t442.c1 = t649.c536870914
           AND t649.c536870939 > 1
         GROUP BY t442.c1
        HAVING COUNT(DISTINCT t631.c536870922) = COUNT(DISTINCT t649.c536870931)
       );

Ceci vous donnera une liste des colonnes c1 qui ont le même nombre de 631 & amp; 649 entrées de table. Remarque: vous devez faire très attention à l'utilisation de DISTINCT dans vos requêtes. Par exemple, dans le cas où vous avez posté les résultats ci-dessus, cela est totalement inutile. souvent, il agit comme une sorte de papier peint pour couvrir les erreurs dans les requêtes qui ne renvoient pas les résultats à votre guise en raison d'une contrainte manquée dans la clause WHERE (& "; Hmm, ma requête renvoie des dupes pour toutes ces valeurs Eh bien, un DISTINCT résoudra ce problème & Quot;).

Autres conseils

Quel est le résultat de:

SELECT COUNT (DISTINCT t631.c536870922),
       COUNT (DISTINCT t649.c536870931)
          FROM t442, t658, t631, t649
         WHERE t442.c1 = t658.c536870930
           AND t442.c200000003 = 'Network'
           AND t442.c536871139 < 2
           AND t631.c536870913 = t442.c1
           AND t658.c536870925 = 1
           AND (t442.c7 = 6 OR t442.c7 = 5)
           AND t442.c536870954 > 1141300800
           AND (t442.c240000010 = 0)
           AND t442.c1 = t649.c536870914
           AND t649.c536870939 > 1

Si les deux colonnes n’ont jamais des valeurs égales, il est logique d’ajouter la clause HAVING éliminerait toutes les lignes du jeu de résultats.

COUNT(DISTINCT column) ne compte pas NULL valeurs:

SELECT  COUNT(DISTINCT val1)
FROM    (
        SELECT  NULL AS val1
        FROM    dual
        )

---
0

Cela pourrait-il être le cas?

Je voudrais plutôt mettre les conditions de la clause HAVING dans la clause WHERE. Y a-t-il une raison pour laquelle vous avez choisi AVOIR? Pour info, HAVING est un filtre qui est effectué après le renvoi du jeu de résultats, ce qui peut entraîner des résultats inattendus. En outre, il n'est pas utilisé dans l'optimisation de la requête. Si vous n’avez pas besoin d’utiliser AYANT, je vous conseillerais de ne pas l’utiliser.

Je suggérerais d'ajouter les comptes à la clause SELECT, puis de les joindre à la clause WHERE.

Si je fais cela:

SELECT distinct t442.c1, count(distinct t631.c536870922), 
    count (distinct t649.c536870931)
          FROM t442, t658, t631, t649
         WHERE t442.c1 = t658.c536870930
           AND t442.c200000003 = 'Network'
           AND t442.c536871139 < 2
           AND t631.c536870913 = t442.c1
           AND t658.c536870925 = 1
           AND (t442.c7 = 6 OR t442.c7 = 5)
           AND t442.c536870954 > 1141300800
           AND (t442.c240000010 = 0)
           AND t442.c1 = t649.c536870914
           AND t649.c536870939 > 1
           group by t442.c1
           having count(distinct t631.c536870922)= 
                         count (distinct t649.c536870931)

Je vois les 23 lignes à compter. La suppression de l’instruction HAVING renvoie 24 lignes, celle qui ne répond pas aux critères HAVING.

EDIT: Résultats de la requête, comme demandé par Steve Broberg:

row | t442.c1         | cnt t631 | cnt 649
-------------------------------------------
1   | CHG000000230378 |    2     |    1
2   | CHG000000230846 |    1     |    1
3   | CHG000000232562 |    1     |    1
4   | CHG000000232955 |    1     |    1
5   | CHG000000232956 |    1     |    1
6   | CHG000000232958 |    1     |    1
7   | CHG000000233027 |    1     |    1
8   | CHG000000233933 |    1     |    1
9   | CHG000000233934 |    1     |    1
10  | CHG000000233997 |    1     |    1
11  | CHG000000233998 |    1     |    1
12  | CHG000000233999 |    1     |    1
13  | CHG000000234001 |    1     |    1
14  | CHG000000234005 |    1     |    1
15  | CHG000000234009 |    1     |    1
16  | CHG000000234012 |    1     |    1
17  | CHG000000234693 |    1     |    1
18  | CHG000000234696 |    1     |    1
19  | CHG000000234730 |    1     |    1
20  | CHG000000234839 |    1     |    1
21  | CHG000000235115 |    1     |    1
22  | CHG000000235224 |    1     |    1
23  | CHG000000235488 |    1     |    1
24  | CHG000000235847 |    1     |    1 

La première ligne est filtrée correctement si j'inclus la clause HAVING.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top