2016-04-26 6 views
2

Ich habe eine Abfrage, die wie folgt aussieht. Es verwendet ein cte:Linke Join Rückgabe der Anzahl von 1, obwohl keine Zeilen für diese Anzahl vorhanden sind?

SELECT d.hour, 
     hourkey, 
     range, 
     COUNT(*) as 'count' 
FROM dimhour d 
    LEFT JOIN cte2 
     ON d.hour = cte2.hourkey 
     AND range IS NOT NULL 
WHERE d.hour <= 23 
GROUP BY d.hour, 
     hourkey, 
     range     
ORDER BY d.hour DESC 

Dies ist das Ergebnis dieser Abfrage ist:

hour hourkey range count 
18  NULL  NULL  1 
17  NULL  NULL  1 
16  NULL  NULL  1 
15  15  99%  15 
14  14  99%  15 
13  13  99%  15 
12  12  99%  15 
11  11  99%  15 
10  10  99%  15 

Das Ergebnis cte2 ist zu groß, um eine Nachricht schreiben, aber ich kann Ihnen sagen, dass die Stunden, wo cte2.hourkey ist null Keine einzige Zeile innerhalb cte2. Es gibt nichts nach Hr15, das möglicherweise eine positive Zahl für count(*) zurückgeben könnte. Aber count(*) gibt irgendwie 1 für diese zurück.

Warum gibt diese Abfrage eine count(*) von 1 für nicht vorhandene Stunden zurück und wie kann ich sie entfernen?

+2

Versuchen Sie 'count (cte2.hourkey)'. – Kateract

+0

Es gibt '0' zurück, was besser ist, aber diese Zeilen werden immer noch im Ergebnis angezeigt. Und ich habe keine Ahnung, wie ich sie entfernen kann. – rbhat

+1

Verwenden Sie dann einen 'inneren' Join, wenn Sie nicht möchten, dass die Nullwerte angezeigt werden, oder habe ich Sie falsch verstanden? – Sherlock

Antwort

3

COUNT(*) gibt eine Anzahl aller Zeilen in einer bestimmten Gruppe zurück, einschließlich der Zeile, in der sie sich befindet. Wenn Sie eine bestimmte Spalte zählen möchten, müssen Sie die Spalte angeben, z. B. COUNT(cte2.hourkey). Dies zählt Nicht-Null-Datensätze innerhalb der Gruppe.

SELECT d.hour, hourkey, range, COUNT(cte2.hourkey) AS [count] 
FROM dimhour d LEFT JOIN cte2 ON 
d.hour = cte2.hourkey 
AND range IS NOT NULL 
WHERE d.hour <= 23 
GROUP BY d.hour, hourkey, range     
ORDER BY d.hour desc 

Wenn Sie nicht die Zeilen wollen überhaupt zeigen, benötigen Sie einen INNER JOIN statt eines LEFT JOIN:

SELECT d.hour, hourkey, range, COUNT(cte2.hourkey) AS [count] 
FROM dimhour d INNER JOIN cte2 ON 
d.hour = cte2.hourkey 
AND range IS NOT NULL 
WHERE d.hour <= 23 
GROUP BY d.hour, hourkey, range     
ORDER BY d.hour desc 
+0

'count (*)' ist gleich 0, was mehr Sinn macht. Aber sie werden immer noch angezeigt. – rbhat

+0

@rchatup Aktualisiert nach Ihrem Kommentar – Kateract

1

Der Ausdruck:

count(*) as [count] 

gibt die Anzahl der Zeilen in der Ergebnismenge. LEFT JOIN garantiert mindestens eine Zeile, auch wenn sie nicht übereinstimmt.

die Spiele zählen, dann einer der für die JOIN verwendeten Spalten zählen (oder Primärschlüssel):

count(cte2.hourkey) as [count] 

Hinweis: Nur einfache Anführungszeichen für String und Datum Konstanten verwenden. Ihre Verwendung für Spalten wird in der Zukunft wahrscheinlich zu Problemen führen.

0

aus einer anderen Perspektive zu beantworten, ich glaube, in einer Art und Weise sein kann, leichter zu verstehen:

Wenn Sie die GROUP BY nehmen, erhalten Sie:

 
hour hourkey range 
18  NULL  NULL 
17  NULL  NULL 
16  NULL  NULL 
15  15  99% 
15  15  99% 
15  15  99% 
15  15  99% 
15  15  99% 
15  15  99% 
15  15  99% 
15  15  99% 
15  15  99% 
15  15  99% 
15  15  99% 
15  15  99% 
15  15  99% 
15  15  99% 
15  15  99% 
14  14  99% 
... 

Wenn Sie jetzt Gruppe von hour, hourkey, range, wie viele Zeilen sehen Sie für 18, NULL, NULL? Ich sehe eine Reihe. Es ist genau dort oben. Das ist, was COUNT(*) zurückgibt.

Und so geht man auch das an: Die Anzahl, die Sie wollen, ist das eine Zahl, die Sie leicht aus diesem Ergebnissatz erhalten können? Wenn nicht, dann suchen Sie nach einem anderen Ansatz. In Ihrem Fall scheinen Sie die Gruppierung unter cte2 vorzunehmen. Schreibe das stattdessen!

select d.hour, sub.hourkey, sub.range, sub."count" 
from dimhour d 
left join (
    select cte2.hourkey, cte2.range, count(*) as "count" 
    from cte2 
    where cte2.range is not null 
    group by cte2.hourkey, cte2.range 
) as sub 
on d.hour = sub.hourkey 
where d.hour <= 23 
order by d.hour desc 

Ein Unterschied besteht darin, dass nun statt 0, Sie NULL zu bekommen, aber Sie ISNULL(sub."count", 0) das vermeiden verwenden könnte, wenn es Sie stört.

Verwandte Themen