2017-05-30 3 views
0

Ich benutze SQL Server. Ich habe Tabelle mit Stundenwerten für verschiedene Aufgaben und Tag 1 bis 7, wie so (Tabelle TaskHours):SQL Server - kann keine Zeilen mit Summe> 0 auswählen

 | TaskID | Hours1 | Hours2 | Hours3 | Hours4 | Hours5 | Hours6 | Hours7 | 
     | 1  | NULL | 10  | NULL | NULL | NULL | NULL | NULL | 
     | 2  | NULL | NULL | 0  | NULL | NULL | NULL | NULL | 
     | 3  | 0  | NULL | 0  | NULL | 0  | 0  | NULL | 
     | 4  | 3  | 3  | 0  | 3  | NULL | NULL | 3  | 
     | 5  | NULL | NULL | NULL | NULL | NULL | NULL | NULL | 

Ich brauche berechnen nur die Summe der Stunden für jede TaskId und wählen Sie diejenigen von ihnen, nur das hat die Summe der Stunden> 0 Aber wenn ich versuche zu schreiben:

SELECT TaskID, Hours1, Hours2, Hours3, Hours4, Hours5, Hours6, Hours7, 
     SUM(ISNULL(Hours1, 0) + ISNULL(Hours2, 0) + ISNULL(Hours3, 0) + ISNULL(Hours4, 0) 
     + ISNULL(Hours5, 0) + ISNULL(Hours6, 0) + ISNULL(Hours7, 0)) AS TotalHours 
    FROM TaskHours 
    WHERE TotalHours > 0 

dann bekomme ich den Fehler:

Invalid column name 'TotalHours'. 

Was ich tue, falsch machen und wie man repariere es?

+0

Dies ist eine Konsequenz der logischen Verarbeitungsreihenfolge von SQL Server (https://destinationdata.wordpress.com/2016/01/10/the-logical-processing-order-3/). TL/DR: Aliase aus der select-Klausel sind nur für die Bestellung von verfügbar. Cross-Apply- und Unterabfragen können das umgehen. –

Antwort

4

Sie können dies wie unten

in Unterabfrage verwenden
SELECT * from (
    SELECT TaskID, Hours1, Hours2, Hours3, Hours4, Hours5, Hours6, Hours7, 
    ISNULL(Hours1, 0) + ISNULL(Hours2, 0) + ISNULL(Hours3, 0) + ISNULL(Hours4, 0) 
    + ISNULL(Hours5, 0) + ISNULL(Hours6, 0) + ISNULL(Hours7, 0) AS TotalHours 
    FROM TaskHours ) a 
WHERE a.TotalHours > 0 
+0

Vielen Dank. –

+1

Für dieses einfache Beispiel ist die Unterabfrage wahrscheinlich in Ordnung.Aber es ist erwähnenswert, dass es für Datenbanken oft von einem Performance-Standpunkt aus gesehen sinnvoll ist, den komplizierten Auswahl-Ausdruck in eine where- oder group by-Klausel zu kopieren und einzufügen. Und dann duschen Sie danach, weil Sie sich so dreckig fühlen, wenn Sie Code wie diesen wiederholen. –

+0

Die Schwierigkeit ergibt sich aus der Tatsache, dass das Schema nicht normalisiert ist. Wenn wir die Stunden in einer Kind-Tabelle (1: n) mit nur einer "Stunden" -Spalte haben, können wir ein einfaches 'SELECT SUM (Stunden)' mit 'GROUP BY TaskID' schreiben. –

2

Zu meinem Verständnis ist das Problem, dass TotalHours noch nicht existiert, wenn Sie die WHERE Klausel schreiben.

So, hier ist meine Lösung:

SELECT * FROM(
SELECT TaskID, Hours1, Hours2, Hours3, Hours4, Hours5, Hours6, Hours7, 
     (IFNULL(Hours1, 0) + IFNULL(Hours2, 0) + IFNULL(Hours3, 0) + IFNULL(Hours4, 0) + IFNULL(Hours5, 0) + IFNULL(Hours6, 0) + IFNULL(Hours7, 0)) 
     AS TotalHours FROM taskhours) as res WHERE res.TotalHours > 0; 

Lassen Sie mich erklären. Dies nennt man SubQueries. Welches sind Abfragen in Abfragen? Wenn Sie den Code lesen, den ich gerade gepostet habe, werden Sie die folgende Struktur bemerken.

SELECT * FROM (subquery) as fooName WHERE fooName.foo = 'something'; 

Diese Struktur erzwingt, dass die Unterabfrage vollständig aufgelöst wird, bevor die äußere Struktur aufgerufen wird. Also in Ihrem Fall:

SELECT * FROM(subquery) as res WHERE res.TotalHours > 0; 

Jetzt TotalHours existiert seit 'Unterabfrage', die

(IFNULL(Hours1, 0) + IFNULL(Hours2, 0) + IFNULL(Hours3, 0) + IFNULL(Hours4,0) + IFNULL(Hours5, 0) + IFNULL(Hours6, 0) + IFNULL(Hours7, 0)) AS TotalHours 

behoben wurde hat.

Eine andere Sache. Ich entfernte die SUM() weil Sie gesagt haben:

"since I need just calculate the sum of hours for each TaskID and select only those of them that has the Sum of hours > 0."

SUM() werden alle tatsächlich summieren die Ergebnisse aller Zeilen Ihrer Ausgabe, die Sie mit den Gesamtstunden aller TaskIDs in einer einzigen Zeile wie so verlassen:

With SUM()

Und zu meinem Verständnis müssen Sie etwas wie folgt aus: Without SUM()

Endlich: IFNULL() ist das Äquivalent von ISNULL() in MYSQL.

Verwandte Themen