2011-07-20 51 views
2

考慮以下查詢:獲取計數到時存在返回0()查詢是假

SELECT M.year, COUNT(C.eid) 
    FROM Card AS C, Month AS M 
    WHERE EXISTS(SELECT 1 FROM Charge AS CH 
       WHERE CH.usingcard=C.eid AND CH.year=M.year) 
    GROUP BY M.year 

其中EXISTS是用來避免「充電」給定年/卡改變計數匹配的數量。 pb是我想爲每個可能的'Month'行生成的行,例如,當沒有匹配的'Charge'時,我希望得到0作爲計數,而我目前沒有任何行。

沒有EXISTS,我可以使用外連接。對於NOT EXISTS()的情況,我也可以使用一個查詢返回0的UNION。

任何人有更聰明的想法?

+1

問題看起來不清楚 – sll

+0

你'UNION'的建議肯定會工作(如將一個'OUTER JOIN',指出這不過是UNION'的'特殊情況)。那麼,「聰明」是什麼意思? – onedaywhen

回答

2

這就避免了多費用記錄的問題:

SELECT M.year, COUNT(distinct CH.usingcard) 
FROM Card AS C 
CROSS JOIN Month AS M 
LEFT JOIN Charge CH on CH.usingcard=C.eid AND CH.year=M.year 
GROUP BY M.year 

該如何計算可不同卡在今年被指控。非連接行將有CH.usingcard爲空,這將不計算在內。

+0

我仍然得到一個空集而不是顯示零計數的行(它也會在SQL Server上生成一個錯誤,無法綁定多部分標識符「C.eid」。) – onedaywhen

+0

對不起 - 我忽略了'LEFT ' - 現在試試。 Re C.eid:給我休息一下......我從你的問題中解決了這個問題。您沒有發佈架構,所以我們必須猜測。您需要將C.eid替換爲「charge」表中的加入列的任何列。 – Bohemian

+0

當我僅僅是同行評審答案時,你誤會了我提問的問題;) – onedaywhen

-1

如果所有參數均爲NULL,則COALESCE將返回NULL。

COALESCE(expression1,...n) is equivalent to the following CASE expression: 

CASE 

    WHEN (expression1 IS NOT NULL) THEN expression1 

    WHEN (expression2 IS NOT NULL) THEN expression2 

    ... 

    ELSE expressionN 

END 

以下示例顯示了COALESCE如何從具有非空值的第一列中選​​擇數據。

SELECT Name, Class, Color, ProductNumber, 
COALESCE(Class, Color, ProductNumber) AS FirstNotNull 
FROM Production.Product ; 
+0

@Tim發帖:仍然不是一個好回答 – gbn

+0

你的回答與這個問題有什麼關係? – onedaywhen

1

的NOT EXISTS是不含0計數:如預期

如果你想零個計數,那麼你需要的OUTER JOIN。然而,你的FROM子句是一個CROSS JOIN,所以你會得到錯誤的計數。你可以忽略的卡表,因爲usingcard具有相同的數據(否則你不會使用它在你EXISTS)

正是這種簡單...

SELECT 
    M.year, COUNT(CH.usingcard) 
FROM 
    Month AS M 
    LEFT JOIN 
    Charge AS CH On CH.year = M.year 
GROUP BY 
    M.year 
+0

「你可以忽略卡表」 - 你能解釋一下你的邏輯飛躍嗎? – onedaywhen

+0

@onedaywhen:爲什麼加入時CH.usingcard = C.eid?您擁有CH.usingcard所需的所有信息。除非OP想要所有卡/月份組合,然後加入...但是,然後按月分組,因此使用卡仍不會增加任何值。您可以自由地*貢獻*而不是*批評* ... – gbn

+0

@onedaywhen:OP的原始問題不需要*兩個*表,因爲它實質上是做的是計算每一年存在的'Charge'中存在的卡在'Charge'中。現在,OP已表示希望考慮所有可能的年份,這意味着在「月份」表中顯示的年份。因此,您需要使用@gbn的答案中的左連接。 –

-1

您可以將NULLIF功能,可在計數功能中使用。該函數有兩個參數:如果參數相等,則返回null,否則返回第一個參數的值。

SELECT M.year, COUNT (NULLIF (CH.usingcard, NULL)) 
FROM Month as M left join Charge as CH 
ON CH.Year = M.Year 
GROUP BY M.year 
+0

當NULLIF()的第二個參數是NULL時,它將不起作用。 – onedaywhen

+0

@Onayaywhen:確切地說 - 空位不會被計數。業務執行部門表示,他希望在沒有用處的月份(年)看到0。使用「正常」計數和左連接將始終給出至少爲1的計數。 –

+0

想一想:「如果參數相等」。在'CH.usingcard'爲'NULL'的情況下,它將返回'NULL'。當'CH.usingcard'不是'NULL'時,它將返回'CH.usingcard'。兩種情況下的結果都與'CH.usingcard'相同,所以'NULLIF()'不起作用。當第二個參數爲「NULL」時,每種情況也適用。 「如果參數是相等的」 - 告訴我,在SQL中當'NULL = NULL'評估TRUE? – onedaywhen