2012-11-30 44 views
2

我想從兩個表,一個主表和一個事務表中拉出記錄。我的Master表包含我所有的帳戶ID。我的transaction表具有由這些帳戶運行的具有3列的任何交易:activity date,incomecharge typeSQL Server Management Studio 2008 - 爲什麼我的左連接不提供空記錄?

transaction表中,其中一些帳戶可能根本不顯示,因爲它們在給定的日期範圍內未執行交易。不過,當我查詢這些帳戶時,仍然需要這些帳戶顯示在我的結果列表中。

所以,我的數據是這樣的:

 Master Table:       Transaction Table: 

    | AccountID |    | AccountID | ChargeType | ActivityDate| Income | 
    --------------    ------------------------------------------------- 
    |  1  |    |  2  | 2000 | 8/31/2012 | $99.00 | 
    |  2  |    |  3  | 2000 | 7/31/2012 | $79.00 | 
    |  3  |    |  5  | 2000 | 9/30/2012 | $79.00 | 
    |  4  | 
    |  5  | 

我的查詢目前看起來像:

select 
    a.AccountID, 
    b.ChargeType, 
    b.ActivityDate, 
    b.Income 
From 
    MasterTable as A 
left join 
    TransactionTable as B on a.AccountID = b.AccountID 
where 
    a.AccountID in ('1','2','3','4','5') 
    and 
    b.ActivityDate between '5/1/2012' and '11/30/2012' 

據我瞭解,此查詢應該列出我選擇了全部5個賬戶,顯示在TransactionTable中找不到的帳戶的值NULL

結果我想到:

 | AccountID | ChargeType | ActivityDate| Income | 
     ------------------------------------------------- 
     |  1  | NULL |  NULL | NULL | 
     |  2  | 2000 | 8/31/2012 | $99.00 | 
     |  3  | 2000 | 7/31/2012 | $79.00 | 
     |  4  | NULL |  NULL | NULL | 
     |  5  | 2000 | 9/30/2012 | $79.00 | 

不正確的結果我收到代替:

  | AccountID | ChargeType | ActivityDate| Income | 
     ------------------------------------------------- 
     |  2  | 2000 | 8/31/2012 | $99.00 | 
     |  3  | 2000 | 7/31/2012 | $79.00 | 
     |  5  | 2000 | 9/30/2012 | $79.00 | 

我認爲我在這裏誤解的東西根本。任何幫助是極大的讚賞!

在此先感謝!

回答

6

原因是你有where子句中引用的「b」表,所以NULL值被過濾掉。

移動狀態的on條款:

From 
    MasterTable A left join 
    TransactionTable B 
    on a.AccountID=b.AccountID and 
     a.AccountID in ('1','2','3','4','5') and 
     b.ActivityDate between '5/1/2012' and '11/30/2012' 
+1

爲什麼要將('1','2','3','4','5')部分中的'a.AccountID移動到'on'子句中?那件作品還不屬於「哪裏」?我知道這會不會影響結果,但語義那塊邏輯對'join' – ean5533

+0

因爲戈登描述了爲什麼查詢不工作選爲最佳答案沒有影響。你不能在where子句中引用正確的表。 – tcshain

+0

@ ean5533。 。 。對於左表上的過濾邏輯是在「on」子句還是在「where」子句中,沒有正確的答案。有人認爲「過濾」邏輯應該在'where'中,並且在'on'中加入邏輯。但是,表b上的條件似乎對大多數人來說都是過濾的,但它仍然屬於'on'子句。對我而言,我可能傾向於使用'where'b.ActivityDate'2012-01-05'和'2012-11-30'之間或者b.AccountId爲NULL',因爲這明確處理了'left outer join'。但是,學習SQL的人應該使用'on'子句學習正確的方法。 –

1

更改您的WHERE子句的最後一個過濾器; SQL Fiddle Example

DECLARE @d1 DATETIME, @d2 DATETIME 
SELECT @d1 = '5/1/2012', @d2 = '11/30/2012' 


SELECT ... 
WHERE a.AccountID in (1,2,3,4,5) AND 
ISNULL(b.ActivityDate, @d1) BETWEEN @d1 and @d2 
+1

-1:將連接謂詞移動到WHERE子句中會使查詢的行爲像一個INNER JOIN而不是一個LEFT OUTER JOIN。 –

+0

(我不是下來的選民)。我建議不要採用這種方法,因爲它在'ISNULL'中使用了一個任意的硬編碼值。這個價值沒有語義含義,並且讓任何人在後面閱讀代碼時感到困惑。 – ean5533

+0

@Norla看看我上面給出的小提琴示例。你能解釋我的意思嗎? – Kaf

1

我會使用以下方法:

(b.ActivityDate is NULL or b.ActivityDate between '5/1/2012' and '11/30/2012') 

使原來的查詢變得

select 
     a.AccountID, 
     b.ChargeType, 
     b.ActivityDate, 
     b.Income 
From 
     MasterTable as A 
     left join 
     TransactionTable as B on a.AccountID=b.AccountID 
where 
     a.AccountID in ('1','2','3','4','5') 
     and 
     (b.ActivityDate is NULL or b.ActivityDate between '5/1/2012' and '11/30/2012') 

但下面的答案可能是更好的。

+0

你會在那裏添加? – tcshain

+0

@tcshain在'2012年5月1日'和'11/30/2012'之間使用它來代替'b.ActivityDate' – ean5533

0

您可以簡單地使用下面的代碼:

SELECT 
    A.AccountID, 
    B.ChargeType, 
    B.ActivityDate, 
    B.Income 
From MasterTable AS A 
LEFT JOIN TransactionTable AS B 
ON A.AccountID = B.AccountID 

如果你在代碼中使用B.ActivityDate BETWEEN '5/1/2012' AND '11/30/2012'條件,那麼它不會產生你期望的結果。因爲對於AccountID = 1,ActivityDateNULL。所以,用AccountID = 1記錄不會滿足你的條件。

+1

您應該停止製作垃圾郵件答案,而應該像這樣做更多......但不包括您的網站鏈接。如果你不斷髮布你的鏈接,你可能會發現你的整個帳戶被刪除 - 而不僅僅是你的垃圾郵件。 –

相關問題