2009-08-16 52 views
14

我最近問了一個關於自我加入的問題,我得到了一個很好的答案。MYSQL自加入如何工作?

該查詢的目的是查找1天后Event1之後的Event2的ID,開始日期和價格。

代碼很好。 但我不明白。

是否有人可以儘可能詳細地解釋 - 查詢的不同部分是什麼以及他們做了什麼?

SELECT event2.id, event2.startdate, event2.price 
FROM mm_eventlist_dates event1 
JOIN mm_eventlist_dates event2 
ON event2.startdate = date_add(event1.enddate, INTERVAL 1 DAY) 
WHERE event1.id=$id 

我真的很感謝您的幫助,無論出於何種原因,我真的很難將這個包裹在我的頭上。

+11

假設event1和event2是兩個完全不相關的表,它們恰好包含完全相同的數據。 – 2009-08-16 14:50:56

回答

17

我試圖理解這一點的方法是在標爲event1和event2的第一塊上寫出兩個列表。然後列出每個列表中的幾條記錄(列表將相同),現在從下面的描述中的WHERE開始。

我們從兩個表中獲取數據(OK使用了兩次相同的表,但要儘量忽略的時刻)

FROM mm_eventlist_dates event1 
JOIN mm_eventlist_dates event2 

這可能有助於從下往上看的休息。

WHERE event1.id=$id 

所以我們想要event1中有指定記錄ID的記錄。據推測,這只是一個記錄。現在我們知道事件結束後的第二天。

date_add(event1.enddate, INTERVAL 1 DAY) 

現在告訴我們,從事件2的記錄,他們需要開始在該日期,

ON event2.startdate = date_add(event1.enddate, INTERVAL 1 DAY) 

我們現在有兩個記錄確定,我們想要什麼領域?

SELECT event2.id, event2.startdate, event2.price 

哦,只是從我們的開始日期我們想出的領域。

+0

感謝您的幫助。 – 2009-08-17 15:46:25

8

當您在查詢中創建連接時,您確實在做這件事 - 將兩個表連接在一起。這可以是2個不同的或2個相同的表,這並不重要。指定聯接時,如果表格不同,爲表格創建別名(在查詢的其餘部分中引用它的名稱)非常有用,如果它們相同,則爲必要。您的查詢正在表1(事件1),具有列:

event1.id, event1.startdate, event1.price 

,並加入表2(事件2):

event2.id, event2.startdate, event2.price 

這讓你對結果集:

event1.id, event1.startdate, event1.price, event2.id, event2.startdate, event2.price 

加入的標準規定爲:

ON event2.startdate = date_add(event1.enddate, INTERVAL 1 DAY) 

這是說'對於事件1中的每一行,加入事件2中startdate後1天的開始日期中的行(s)'

然後,因爲您只對一個事件的數據感興趣子句限制了結果集。

WHERE event1.id=$id 

最後,因爲你不從事件1需要你的SELECT語句只需選擇從結果集的事件2列的原始事件的信息:

SELECT event2.id, event2.startdate, event2.price 
+0

謝謝,您的回覆非常有幫助。 – 2009-08-17 15:47:04

6

自通過引用相同的連接工程表兩次使用不同的選擇標準。將對錶格的每個引用都視爲通過過濾原始表格創建的不同「虛擬表格」。通常,其中一個表使用WHERE子句「過濾」,第二個表在連接子句中「過濾」。這是最有效的方法,也可以在連接子句中「過濾」。

因此,我們有兩個基於同一個基礎表中的數據的虛擬表格,它們連接在一起就好像它們是兩個完全獨立的表格。

它的關鍵在於你將數據存儲在一張表中,該表根據上下文略有不同的含義。

考慮一桌子的人,每一個獨特的ID和父親

id name fatherID 
    1 Joseph [null] 
    2 Greg  1 

    SELECT child.name as childName, father.name as fatherName 
     FROM people as child 
     INNER JOIN people as father on (child.fatherID = father.id) 

列將產生1行

childName fatherName 
    Greg  Joseph 
+0

這是我可以請求的最簡單的例子。非常感謝你。 – 2009-08-17 15:47:42

5

聯接將基於特定標準的兩個表。 ON條款後面的標準是。

如果您將自己與表連接在一起,它實際上與創建表的副本相同,將其重命名並使用該副本執行連接。

例如

 
Table foo   Table bar 
+---+---+---+  +---+---+---+ 
| a | b | c |  | a | d | e | 
+---+---+---+  +---+---+---+ 
| 1 | 2 | 3 |  | 1 | 0 | 0 | 
+---+---+---+  +---+---+---+ 
| 1 | 3 | 4 |  | 2 | 9 | 3 | 
+---+---+---+  +---+---+---+ 
| 1 | 3 | 5 | 
+---+---+---+ 
| 2 | 4 | 6 | 
+---+---+---+ 

如果我們這樣做

select * from foo join bar on (foo.a = bar.a and foo.c > 4) 

我們最終

 

foo join bar on (foo.a = bar.a and foo.c > 4) 
+---+---+---+---+---+ 
| a | b | c | d | e | 
+---+---+---+---+---+ 
| 1 | 3 | 5 | 0 | 0 | 
+---+---+---+---+---+ 
| 2 | 4 | 6 | 9 | 3 | 
+---+---+---+---+---+ 

現在,

SELECT event2.id, event2.startdate, event2.price 
FROM mm_eventlist_dates event1      
JOIN mm_eventlist_dates event2 
ON event2.startdate = date_add(event1.enddate, INTERVAL 1 DAY) 
WHERE event1.id=$id 

該查詢遵循相同的原則,但具有表mm_eventlist_dates的兩個實例,一個用作event1,另一個用作event2。我們可以把這看作像有兩個表一樣,並且像真正的兩個表格一樣執行連接。

的加入在這種情況下的標準是,對錶事件2,起始日期的結束日期加上表事件1的第一天比賽。

where子句限制之上的聯接執行什麼,在這種情況下,它執行聯接僅在具有所提供的ID事件1表中的行。