2012-06-16 27 views
1

我有兩個表如圖所示here不同的行爲使用JOIN ON和JOIN ON

我正在嘗試取nameregister變量當register變量不存在值存在。

使用下面的查詢我得到的是here

SELECT t2.name, t1.register, t1.mydate 
FROM time t1 
RIGHT JOIN user t2 
ON t2.user_id=t1.user_id 
WHERE (t1.register = 'absent' OR t1.register is null) 

當我使用下面的查詢,我得到錯誤的結果如圖here

SELECT t2.name, t1.register, t1.mydate 
FROM time t1 
RIGHT JOIN user t2 
ON t2.user_id=t1.user_id AND (t1.register = 'absent' OR t1.register is null) 

我的問題是:爲什麼我在上述情況下得到不同的結果。我在ON子句本身中使用WHERE條件,以便我不需要編寫WHERE條件。

有人能指引我正確的方向嗎?

+0

的查詢相同但看看sqlfiddle:p –

+0

查詢看起來與我一樣 – iedoc

+0

@iedoc,他們是。我從小提琴更新了它們。 – Ben

回答

3

如果將"t1.register = 'absent' OR t1.register is null"條件置於WHERE子句中,它將在連接之後應用,而如果將其放入ON子句中,則會影響連接。

這是絕對正常和期望的行爲:)

在這裏,你必須把它的WHERE子句:)

0

你的問題涉及到你的查詢執行的順序英寸 正常順序是

From 
JOIN 
WHERE 
SELECT 

所以,在第一個例子中

SELECT t2.name, t1.register, t1.mydate 
FROM time t1 
RIGHT JOIN user t2 
ON t2.user_id=t1.user_id 
WHERE (t1.register = 'absent' OR t1.register is null) 

首先,這兩個表將共同基於所述條件t2.user_id=t1.user_id(使用內加入),然後將所有未匹配的來自時間的行表將被添加到臨時結果表中。最後,將WHERE子句(t1.register = 'absent' OR t1.register is null)中的條件應用於臨時表以產生最終結果。

在第二個範例

SELECT t2.name, t1.register, t1.mydate 
FROM time t1 
RIGHT JOIN user t2 
ON t2.user_id=t1.user_id AND (t1.register = 'absent' OR t1.register is null) 

首先,兩個表連接在一起(使用內加入)的基礎上的條件t2.user_id=t1.user_id AND (t1.register = 'absent' OR t1.register is null)。接下來,將時間的所有不匹配行添加到結果中。

對於所有這些,兩個查詢的結果是不同的。

如果使用INNER JOIN,則WHERE或ON子句中的條件會產生相同的結果。如果您使用OUTER JOIN(左/右/橫),它們只會有所不同。

1

我通常不會使用右連接,而是左連接...我知道它們實際上是相同的,只是您要從中記錄的連接中的哪個表。正如Olivier所說,WHERE子句是在連接條件之後應用的。我通常會先問問我想要什麼......在你的情況,我想不管登記時間列出的所有用戶...所以,我只想把它作爲

select 
     u.Name, 
     t.register, 
     t.myDate 
    from 
     users u 
     LEFT JOIN time t 
      on u.user_id = t.user_id 

我的左表(總想)是用戶......時間是右表,並且我總是試圖保持我的「ON」連接條件,以表示可讀性的左/右關聯。

現在,這不完全是你想要的,但它從哪裏開始......現在,如何應用「缺席」狀態。由於上述內容已經獲得所有用戶,並且您只希望查看發生「缺席」的條目,請將其添加到JOIN部分,因爲這些是您有興趣查看的唯一條目。

select 
     u.Name, 
     t.register, 
     t.myDate 
    from 
     users u 
     LEFT JOIN time t 
      on u.user_id = t.user_id 
      AND t.register = 'absent' 

因此,只有把「缺席」將展示各自的寄存器,並指明MyDate值的記錄......任何其他記錄,你仍然可以得到每個人。不需要WHERE子句。

但是,如果說你只是想誰是某種類型或狀態的用戶,你可以添加,限制那些「用戶」你想看看......如

select 
     u.Name, 
     t.register, 
     t.myDate 
    from 
     users u 
     LEFT JOIN time t 
      on u.user_id = t.user_id 
      AND t.register = 'absent' 
    where 
     u.SomeStatus = whatever