2010-02-02 99 views
2

我基本上試圖修改this存儲過程。WHERE子句導致表省略LEFT JOIN規則

修改存儲過程:

CREATE PROCEDURE sp1(d1 date, d2 date, client INT(10)) 
    declare d datetime; 

    create TEMPORARY TABLE foo (d date NOT NULL, Amount INT(10) DEFAULT 0); 

    set d = d1; 

    while d <= d2 do 
     insert into foo (d) values (d); 
     set d = date_add(d, interval 1 day); 
    end while; 

    SELECT SUM(p.Amount), foo.d 
    FROM foo LEFT JOIN ItemTracker_dbo.Payment ON foo.d = p.Datetime 
    WHERE p.ClientId = ClientId 
    GROUP BY 
     foo.d; 

    DROP TEMPORARY TABLE foo; 
end PROCEDURE 

注: WHERE子句... p.ClientId =客戶

我是令人頭大我的大腦試圖找出它爲什麼被省略零。

經拆除後WHERE p.ClientId = client程序開始返回NULL ...

爲什麼WHERE子句ommiting空行?我可能誤解了什麼究竟是 a LEFT JOIN是。

我怎麼能過濾SUM(p.Amount)結果只返回總和WHERE clientId = client

回答

3

,如果你把所有的條件進入LEFT JOIN條件應該工作:

SELECT SUM(p.Amount), foo.d 
FROM foo 
LEFT JOIN ItemTracker_dbo.Payment p ON foo.d = p.Datetime AND p.ClientId = ClientId 
GROUP BY 
    foo.d; 
+0

這是可以的,但會更改查詢的語義。 – Romain 2010-02-02 16:11:33

+0

@Romain Muller:我認爲'p'是'Payment'的別名。它在哪裏改變了語義? – 2010-02-02 16:13:58

+0

對我來說工作得很好。接受,因爲你在哪裏第一個15秒 – 2010-02-02 16:14:57

0

的問題是,=運算符是不是空安全的SQL。 NULL = NULL是錯誤的。你必須使用NULL安全的等價物,如果我記得正確的話,在MySQL上是<=>。您也可以使用COALESCE函數或將a=b編寫爲(a=b OR a IS NULL or b IS NULL)

2

移動WHERE條款列入ON條款是這樣的:

SELECT SUM(p.Amount), foo.d 
FROM foo LEFT JOIN ItemTracker_dbo.Payment ON foo.d = p.Datetime 
    and p.ClientId = ClientId 
GROUP BY 
    foo.d; 

通過將客戶端Id比較的WHERE子句中,你有效地將LEFT JOIN回一個INNER JOINClientId

+0

+1提供或多或少相同的答案我做了,但沒有得到接受:) – 2010-02-02 16:20:40

+0

爲什麼感謝你,先生! – RedFilter 2010-02-02 16:40:20

4

首先,是不是你的示例代碼

SELECT SUM(p.Amount), foo.d 
    FROM foo LEFT JOIN ItemTracker_dbo.Payment ON foo.d = p.Datetime 
    WHERE p.ClientId = ClientId 
    GROUP BY 
     foo.d; 

缺少的別名表ItemTracker_dbo.Payment一個p? 即,不應該; t將其讀:

SELECT SUM(p.Amount), foo.d 
    FROM foo 
     LEFT JOIN ItemTracker_dbo.Payment p 
      ON foo.d = p.Datetime 
WHERE p.ClientId = ClientId 
GROUP BY foo.d; 

無論如何,你是有這個問題的原因是,where子句條件不施加直到外後聯接進行處理(其中加入從外側的行因此您需要將where條件移入連接條件:

SELECT SUM(p.Amount), foo.d 
    FROM foo 
     LEFT JOIN ItemTracker_dbo.Payment p 
      ON foo.d = p.Datetime 
       And p.ClientId = ClientId 
GROUP BY foo.d; 
+0

你是對的,我一直在轉移和測試,並沒有選擇它......謝謝 – 2010-02-02 16:13:09

+0

+1爲我提供比我更詳細的答案 – 2010-02-02 16:18:36

+0

非常非常好的答案 – 2010-02-02 18:26:31