2014-02-20 94 views
0

我已經在它兩天了,無法弄清楚。希望可以有人幫幫我。MySQL得到每個項目的最後一個記錄

我有幾個表與一對多的關係。

這是很難解釋的,所以這裏是有關表的例子(文件編號來自另一個表中,並沒有涉及到這個問題,我們在這個例子中尋找文件ID爲1)

Table 1 - history 
+----+---------+---------+-----------+---------------------+ 
| id | file_id | user_id | action_id | datetime   | 
+----+---------+---------+-----------+---------------------+ 
| 1 |  1 |  1 |   1 | 2014-02-19 19:19:49 | 
| 2 |  1 |  1 |   2 | 2014-02-19 19:20:06 | 
| 3 |  1 |  1 |   3 | 2014-02-19 19:32:09 | 
| 4 |  2 |  2 |   1 | 2014-02-20 11:52:59 | 
| 5 |  2 |  2 |   2 | 2014-02-20 11:53:08 | 
+----+---------+---------+-----------+---------------------+ 

Table 2 - file_items 
+----+---------+------------+---------------+ 
| id | file_id | item_id | remark  | 
+----+---------+------------+---------------+ 
| 1 |  1 |   1 | item1 remark | 
| 2 |  1 |   20 | item2 remarks | 
| 3 |  2 |   2 | test   | 
+----+---------+------------+---------------+ 

Table 3 - item_statuses 
+----+----------------+--------------+----------------+----------------------+ 
| id | file_action_id | file_item_id | item_status_id | comment    | 
+----+----------------+--------------+----------------+----------------------+ 
| 1 |    2 |   1 |    1 |      | 
| 2 |    2 |   2 |    1 |      | 
| 3 |    3 |   1 |    2 | status comment  | 
| 4 |    3 |   2 |    1 | item2 status comment | 
| 5 |    5 |   3 |    1 |      | 
+----+----------------+--------------+----------------+----------------------+ 

t1.action_id有關t3.file_action_id

t2.item_id有關t3.file_item_id

t1.file_id有關t2.file_id

我想獲得特定文件的每個項目的最後一個狀態(在這種情況下文件ID爲1)。

期望的結果:

+----------------+-----------------+------------+---------------------+----------------+----------------------+ 
| file_action_id | file_item_id | remark  | file_item_status_id | item_status_id | COMMENT    | 
+----------------+-----------------+------------+---------------------+----------- ----+----------------------+ 
|    3 |   1 | item1 remark |     3 |    2 | status comment  | 
|    3 |   2 | item2 remarks |     4 |    1 | item2 status comment | 
+----------------+--------------+---------------+---------------------+----------------+----------------------+ 

我能得到什麼:

+----------------+-----------------+------------+---------------------+----------------+----------------------+ 
| file_action_id | file_item_id | remark  | file_item_status_id | item_status_id | COMMENT    | 
+----------------+-----------------+------------+---------------------+---------- -----+---------------------+ 
|    3 |   1 | item1 remark |     1 |    1 |      | 
|    3 |   1 | item1 remark |     3 |    2 | status comment  | 
|    3 |   2 | item2 remarks |     2 |    1 |      | 
|    3 |   2 | item2 remarks |     4 |    1 | item2 status comment | 
+----------------+--------------+---------------+---------------------+----------------+----------------------+ 

查詢:

SELECT 
t1.id AS file_action_id, 
t2.id AS file_item_id, 
t2.remark AS remark, 
t5.id AS file_item_status_id, 
t5.item_status_id AS item_status_id, 
t5.comment AS COMMENT 

FROM `file_history` AS t1 

LEFT JOIN `file_items` AS t2 
ON (t1.file_id = t2.file_id) 

LEFT JOIN `file_item_statuses` AS t5 
ON (t2.id = t5.file_item_id) 

WHERE t1.file_id = 1 
AND 
t1.id = (SELECT MAX(id) FROM `file_history` WHERE file_id = 1) 

我試着用GROUP BYORDER BY但它並沒有爲我做的。

SQL FIDDLE HERE

回答

1

好了,你想爲一個特定的文件每個項目的最新狀態,所以,我會做什麼,是一個表做INNER JOIN這隻有最新的狀態。

做這件事,而不是LEFT JOINfile_item_statuses,我會LEFT JOIN用正確的數據的子查詢(子查詢將讓你只與價值最大化狀態的id行,我檢查這個實現它:SQL Select only rows with Max Value on a Column

SELECT fs.id   
    , fs.file_item_id 
    , fs.item_status_id 
    , fs.comment 
FROM file_item_statuses fs 
INNER JOIN (
    SELECT MAX(id) AS id 
    FROM file_item_statuses 
    GROUP BY file_item_id 
    ) maxfs 
ON maxfs.id = fs.id 

而這個子查詢,你必須留下的主要參加吧:

SELECT 
t1.id AS file_action_id, 
t2.id AS file_item_id, 
t2.remark AS remark, 
t5.id AS file_item_status_id, 
t5.item_status_id AS item_status_id, 
t5.comment AS COMMENT 

FROM `file_history` AS t1 

LEFT JOIN `file_items` AS t2 
ON (t1.file_id = t2.file_id) 

INNER JOIN ( 
    SELECT fs.id   
     , fs.file_item_id 
     , fs.item_status_id 
     , fs.comment 
    FROM file_item_statuses fs 
    INNER JOIN (
     SELECT MAX(id) AS id 
     FROM file_item_statuses 
     GROUP BY file_item_id 
    ) maxfs 
    ON maxfs.id = fs.id) AS t5 
ON (t2.id = t5.file_item_id) 

WHERE t1.id = (SELECT MAX(id) FROM `file_history` WHERE file_id = 1) 

GROUP BY file_item_id 

我運行它,準確地扔你想要的結果,享受!

+0

感謝,偉大工程!另一個答案也適用。我沒有太多數據來測試效率。我希望將更有效率的標記作爲兩者都有效的答案。 –

+0

知道它的唯一方法:在插入數百個虛擬數據之後,在您的機器上運行這兩個數據並檢查速度。無論如何,在子查詢中,您可以更改我提供的方式(答案中的第一個選項),並使用我檢查過的答案中的第二個選項來實現它。這樣你以後可以改進它。啊!不要忘記包含適當的索引! (使用您用於連接的字段構建它們) – Chococroc

0

嘗試此查詢

SELECT 
t1.id AS file_action_id, 
t2.id AS file_item_id, 
t2.remark AS remark, 
t5.id AS file_item_status_id, 
t5.item_status_id AS item_status_id, 
t5.comment AS COMMENT 


FROM `file_history` AS t1 

LEFT JOIN `file_items` AS t2 
ON (t1.file_id = t2.file_id) 

LEFT JOIN `file_item_statuses` AS t5 
ON (t2.id = t5.file_item_id) 

WHERE t1.file_id = 1 
AND 
t1.id = (SELECT MAX(id) FROM `file_history` WHERE file_id = 1) 
GROUP BY t1.id,t2.id 
+0

不工作,返回第一條記錄爲每個組 –

1

試試這個:

SELECT 
t1.id AS file_action_id, 
t2.id AS file_item_id, 
t2.remark AS remark, 
t5.id AS file_item_status_id, 
t5.item_status_id AS item_status_id, 
t5.comment AS COMMENT 


FROM `file_history` AS t1 

LEFT JOIN `file_items` AS t2 
ON (t1.file_id = t2.file_id) 

LEFT JOIN `file_item_statuses` AS t5 
ON (t2.id = t5.file_item_id) 

WHERE t1.file_id = 1 
AND 
t1.id = (SELECT MAX(id) FROM `file_history` WHERE file_id = 1) 
# Add the follow condition to fecth max id in file_item_statuses of each item 
# vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv 
and t5.id in (SELECT MAX(t3.id) 
      FROM `file_item_statuses` t3, `file_items` t4 
      WHERE t4.id = t3.file_item_id 
      AND t4.file_id = 1 
      GROUP BY t4.id) 
#GROUP BY t2.id 
#ORDER BY MAX(file_item_status_id) 

SQL Fiddle

+0

謝謝!它正在工作 - 不知道哪個更好/更快。 –

+0

在WHERE子句中小心使用IN,它用來成爲一個高資源消耗者:當你有超過1000個結果時,會很慢。我在SQL的WHERE中使用它只檢索社交網絡中的朋友的帖子,我不得不改變它,因爲當有人有超過300個朋友時,它會瘋狂地放慢查詢 – Chococroc

相關問題