I've been at it for two days, can't figure it out. Hope someone can help me.
I have several tables with one to many relationships.
It is hard to explain, so here are examples of tables concerned (file id comes from another table and is not related to this problem, file id we looking for in this example is 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
is related to t3.file_action_id
t2.item_id
is related to t3.file_item_id
t1.file_id
is related to t2.file_id
I am trying to get last status for each item for a specific file (file id 1 in this case).
Desired result:
+----------------+-----------------+------------+---------------------+----------------+----------------------+
| 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 |
+----------------+--------------+---------------+---------------------+----------------+----------------------+
What I get:
+----------------+-----------------+------------+---------------------+----------------+----------------------+
| 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 |
+----------------+--------------+---------------+---------------------+----------------+----------------------+
Query:
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)
I tried using GROUP BY
and ORDER BY
but it didn't do it for me.
Ok, so you want the latest status for each item for a specific file, so, what I would do, is do the INNER JOIN
with a table which only would have the latest status.
For doing it, instead of LEFT JOIN
with file_item_statuses
, I will LEFT JOIN
with a subquery with the right data (the subquery will get you only the rows with maximum status id value, I checked this to achieve it: 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
And this subquery, you have to LEFT JOIN it with the main:
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
I run it and throw exactly the results you wanted, enjoy!
Try this:
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)
try this query
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.