2015-05-04 28 views
1

服務器NULL結果: SQL Server 2008 R2的
SQL小提琴:http://sqlfiddle.com/#!6/112a6/4/0SQL JOIN沒有顯示時,WHERE子句中使用

我對窮人的主題/標題道歉,但我有一個困難時期口頭說明如何陳述我的問題,所以我會用一個(可能)很長的例子來繪製它:

下面是一個相當簡單的查詢,它可以獲取特定日期範圍內PC的會話數量。注意在這一點上,WHERE子句被註釋掉了。我希望收到的是PC的完整列表,甚至那些在該範圍內有零/空會話的PC。但是,當我添加WHERE子句時,我只能獲得在該範圍內進行會話的PC。這是有問題的,因爲我無法看到那段時間內未使用的個人電腦。

SELECT 
    f_assetnetbiosname, 
    COUNT(f_sessiondate) as 'Sessions' 
FROM 
    tb_assets ass 
LEFT JOIN 
    tb_sessions ses 
    ON 
    ses.f_sessionnetbiosname = ass.f_assetnetbiosname 
--WHERE (f_sessiondate BETWEEN '04/01/2015' AND '04/30/2015') 
GROUP BY f_assetnetbiosname 

======================== =======================================| 
| tb_assets   | | tb_sessions       | 
======================== =======================================| 
| f_assetnetbiosname | | f_sessionnetbiosname f_sessiondate | 
------------------------ ---------------------------------------| 
|  COMP_001   | | COMP_002   03/29/2015 | 
|  COMP_002   | | COMP_002   03/30/2015 | 
|  COMP_003   | | COMP_001   03/30/2015 | 
------------------------ | COMP_001   04/02/2015 | 
          | COMP_001   04/03/2015 | 
          | COMP_001   04/04/2015 | 
          | COMP_001   04/05/2015 | 
          ----------------------------------- 

基於這些結果的查詢將返回以下結果集:

|=================================| 
| f_assetnetbiosname | Sessions | 
|=================================| 
| COMP_001   | 5   | 
| COMP_002   | 2   | 
| COMP_003   | 0   | 
|=================================| 

的問題是,我需要爲實際的日期範圍只搜索。所以,如果我取消了在上面的查詢中的「WHERE」子句,結果集看起來只像下面這樣:

|=================================| 
| f_assetnetbiosname | Sessions | 
|=================================| 
| COMP_001   | 4   | 
|=================================| 

但我需要它看起來像下面這樣我就可以看到了零的電腦會議:

|=================================| 
| f_assetnetbiosname | Sessions | 
|=================================| 
| COMP_001   | 4   | 
| COMP_002   | 0   | 
| COMP_003   | 0   | 
|=================================| 

有沒有人有此修復?請注意,上面的例子就是這個例子。真正的查詢是一個multi-CTE熊貓,但我認爲最好把它降低到最基本的水平,這樣我就不會通過炫耀我的錯誤代碼來對話。

SQL小提琴http://sqlfiddle.com/#!6/112a6/4/0

由於提前,
Beems

+2

上的* *外表添加一個狀態到'Where'子句有效地將外部聯接到內連接。相反,將外部表條件添加到它們的JOIN的ON子句中,如下面的@TimSchmelter所示。 – RBarryYoung

+0

@Beems:這是一個[很好的閱讀](http://www.xaprb.com/blog/2009/04/08/the-dangerous-subtleties-of-left-join-and-count-in-sql/)爲你... –

+0

@PeterSchneider不是。那篇文章只是很多歪曲的危言聳聽,它確實包含了OP所存在的問題,但似乎並不瞭解問題的真正原因是什麼,這不是因爲「人們不明白什麼是什麼LEFT JOIN的確如此「(因爲它暗示的是NULL)。實際上,根據我的經驗,犯這個錯誤的人通常會理解LEFT JOIN非常好,他們通常誤解的是WHERE子句和ON子句之間的區別。 – RBarryYoung

回答

5

你可以把它添加到Join條款:

SELECT 
    f_assetnetbiosname, 
    COUNT(f_sessiondate) as 'Sessions' 
FROM 
    tb_assets ass 
LEFT OUTER JOIN 
    tb_sessions ses 
    ON 
    ses.f_sessionnetbiosname = ass.f_assetnetbiosname 
    AND f_sessiondate BETWEEN '04/01/2015' AND '04/30/2015' 
GROUP BY f_assetnetbiosname 

這裏有一個演示:http://sqlfiddle.com/#!6/112a6/23/0

那是 Join條款和Where的差別,其也被提及here

+0

謝謝,這似乎很好。在這種情況下,只是'LEFT JOIN'和'LEFT OUTER JOIN'之間的區別是什麼?他們似乎都返回了相同的結果。 – Beems

+1

@Beems:沒有區別。 http://stackoverflow.com/questions/406294/left-join-and-left-outer-join-in-sql-server Imo最好是明確的,否則你或你的夥伴總是不得不考慮它是否是'外部連接'。 –

0

這聽起來像你只需要根據日期進行計數,以便您可以將條件計入您的計數。

SELECT f_assetnetbiosname, 
COUNT(CASE WHEN (f_sessiondate BETWEEN '04/01/2015' AND '04/30/2015') 
      THEN 1 ELSE null 
      END) as 'Sessions' 
FROM tb_assets ass 
LEFT JOIN tb_sessions ses ON ses.f_sessionnetbiosname = ass.f_assetnetbiosname 
GROUP BY f_assetnetbiosname 

http://sqlfiddle.com/#!6/112a6/27