2013-01-14 61 views
2

我有點卡住..MySQL的加入/ GROUP一個一對多的關係

我有兩個表

mysql > EXPLAIN event; 
+-------------+--------------+------+-----+---------------------+-----------------------------+ 
| Field  | Type   | Null | Key | Default    | Extra      | 
+-------------+--------------+------+-----+---------------------+-----------------------------+ 
| id   | int(11)  | NO | PRI | NULL    | auto_increment    | 
| name  | varchar(100) | NO | MUL |      |        | 
| extUrl  | varchar(192) | NO |  |      |        | 
+-------------+--------------+------+-----+---------------------+-----------------------------+ 

一個事件可以有許多

mysql> explain eventDate; 
+----------------+--------------+------+-----+---------------------+-----------------------------+ 
| Field   | Type   | Null | Key | Default    | Extra      | 
+----------------+--------------+------+-----+---------------------+-----------------------------+ 
| id    | int(11)  | NO | PRI | NULL    | auto_increment    | 
| category_id | int(11)  | NO | MUL | 0     |        | 
| event_id  | int(11)  | NO | MUL | 0     |        | 
| location_id | int(11)  | NO | MUL | 0     |        | 
| name   | varchar(100) | NO |  |      |        | 
| eventDate  | timestamp | NO |  | 0000-00-00 00:00:00 |        | 
+----------------+--------------+------+-----+---------------------+-----------------------------+ 

我會喜歡通過id查詢事件,location_id下一個即將到來的eventDate,我被卡住瞭如何形成查詢

我現在有這個

SELECT 
     e.id, 
     d.location_id, 
     d.eventDate 
FROM 
     event e 
      INNER JOIN eventDate d ON d.event_id = e.id AND d.eventDate >= CURRENT_TIMESTAMP 
WHERE 
     e.id = 5107 
GROUP BY 
     e.id 
ORDER BY 
     d.eventDate ASC 

現在這個返回一個結果,但我GROUP BY事件,所以我不能確定如何保證真正的下一個EVENTDATE選擇。此外,我沒有使用任何聚合函數(逐個聚合,聚合很多),這似乎不是一個乾淨和明確定義的結果要求--MySQL隨機選擇其中一個eventDate行,現在不是它嗎?

+0

會選擇任何的事件大於或等於當前時間戳。由於您是通過ID對其進行分組的,MySQL不知道哪一行對您更重要。因此,它會選擇它遇到的第一個或最後一個,而不是 - 因爲我相信你希望它 - 下一個upcomming eventDate。你將不得不擴展你的'WHERE'子句和/或給它添加一個'LIMIT'來只選擇1 – Tikkes

+0

是的,我想有下一個即將到來的eventDate,由於' WHERE e.id = 5107'和'GROUP BY e.id',但我不確定'ORDER BY'子句提示MySQL選擇下一個即將出現的'd.eventDate'。有沒有更好的方法 –

回答

2

這應該總是給你的第一個即將發生的事件:

SELECT 
     e.id, 
     d.location_id, 
     d.eventDate 
FROM 
     event e 
      INNER JOIN eventDate d ON d.event_id = e.id 
WHERE 
     e.id = 5107 
     AND 
     d.id = (SELECT d1.id FROM eventDate d1 WHERE d1.event_id = 5107 AND d1.eventDate >= CURRENT_TIMESTAMP ORDER BY d1.eventDate ASC LIMIT 1) 

但更好的方法是添加LIMIT 1到您當前的查詢,並拆卸GROUP BY

SELECT 
     e.id, 
     d.location_id, 
     d.eventDate 
FROM 
     event e 
      INNER JOIN eventDate d ON d.event_id = e.id AND d.eventDate >= CURRENT_TIMESTAMP 
WHERE 
     e.id = 5107 
ORDER BY 
     d.eventDate ASC 
LIMIT 1 
+0

它也可能沒有子查詢,只是在第一個查詢(他發佈的那個)中添加「LIMIT」或者我錯過了什麼? – Tikkes

+0

不,你說得對,我只是加了一個。說實話這是最好的方法。 – Manuel

+0

解決方案一,我認爲會是一種效率低下,想象一個具有數百萬行的eventDate表,即使我將其更改爲AND AND.ID =(SELECT d1.id ...)',解決方案二doen'解決「隨機 - 或不?」的問題選定的eventDate行。我已經得到了一個結果行(e.id = xx + GROUP BY e.id) –