英文:
Need to group by the vehicle id from the online & offline date history logs and get the latest date of history
问题
以下是翻译好的部分:
我有以下表格
- tbl_vehicles
 
| vid | accnt_id | platenumber | 
|---|---|---|
| 1 | 1 | VD101 | 
| 2 | 1 | VD102 | 
- tbl_status_history
 
| id | vid | accnt_id | date_online | date_offline | 
|---|---|---|---|---|
| 1 | 1 | 1 | 2023-02-25 | 0000-00-00 | 
| 2 | 1 | 1 | 0000-00-00 | 2023-02-26 | 
| 3 | 2 | 1 | 0000-00-00 | 2023-02-27 | 
| 4 | 2 | 1 | 0000-00-00 | 2023-02-28 | 
| 5 | 1 | 1 | 0000-00-00 | 2023-03-01 | 
| 6 | 1 | 1 | 2023-03-02 | 0000-00-00 | 
现在,我需要按vid分组,并获取它们的最新状态历史记录。例如,在vid:1下的tbl_status_history中,该vid的最新状态历史记录是在线的,所以vid 1的结果将是日期date_online 2023-03-02。
以下是我的目标结果。
| id | vid | accnt_id | date_online | date_offline | 
|---|---|---|---|---|
| 2 | 1 | 1 | 2023-03-02 | 0000-00-00 | 
| 4 | 2 | 1 | 0000-00-00 | 2023-02-28 | 
我使用了@nnichols的代码,并将其更新为下面的代码,以便获取最新的在线日期,但还没有弄清楚如何在分组之前对两个日期(Online和offline)进行排序
SELECT h.id, h.vid, h.accnt_id, h.date_online, h.date_offline, v.platenumber
FROM tbl_status_history h
JOIN (
    SELECT vid, MAX(date_offline) max_date_offline, MAX(date_online) max_date_online
    FROM tbl_status_history
    GROUP BY vid
) h2 ON h.vid = h2.vid AND h.date_offline = h2.max_date_offline and h.date_online = h2.max_date_online
JOIN tbl_vehicles v ON h.vid = v.vid and h.accnt_id = 1;
英文:
I have below the tables
- tbl_vehicles
 
| vid | accnt_id | platenumber | 
|---|---|---|
| 1 | 1 | VD101 | 
| 2 | 1 | VD102 | 
- tbl_status_history
 
| id | vid | accnt_id | date_online | date_offline | 
|---|---|---|---|---|
| 1 | 1 | 1 | 2023-02-25 | 0000-00-00 | 
| 2 | 1 | 1 | 0000-00-00 | 2023-02-26 | 
| 3 | 2 | 1 | 0000-00-00 | 2023-02-27 | 
| 4 | 2 | 1 | 0000-00-00 | 2023-02-28 | 
| 5 | 1 | 1 | 0000-00-00 | 2023-03-01 | 
| 6 | 1 | 1 | 2023-03-02 | 0000-00-00 | 
Now, I need to group the vid and get their latest status history. For example in vid:1 under tbl_status_history. This vid latest status history is online so the result for vid 1 would be the date_online 2023-03-02.
Below is my target result.
| id | vid | accnt_id | date_online | date_offline | 
|---|---|---|---|---|
| 2 | 1 | 1 | 2023-03-02 | 0000-00-00 | 
| 4 | 2 | 1 | 0000-00-00 | 2023-02-28 | 
I used the code of @nnichols and updated it to the below code to get also the latest online date but had still not worked out how to sort the two dates(Online & offline) before the group by
SELECT h.id, h.vid, h.accnt_id, h.date_online, h.date_offline, v.platenumber
FROM tbl_status_history h
JOIN (
    SELECT vid, MAX(date_offline) max_date_offline, MAX(date_online) max_date_online
    FROM tbl_status_history
    GROUP BY vid
) h2 ON h.vid = h2.vid AND h.date_offline = h2.max_date_offline and h.date_online = h2.max_date_online
JOIN tbl_vehicles v ON h.vid = v.vid and h.accnt_id = 1;
答案1
得分: 0
以下是已翻译的部分:
这是使用 ROW_NUMBER() 生成 "目标结果" 的一种方法:
SELECT h.id, h.vid, h.accnt_id, h.date_online, h.date_offline, v.platenumber
FROM (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY vid ORDER BY GREATEST(date_online, date_offline) DESC) rn
    FROM tbl_status_history
    WHERE accnt_id = 1
) h
JOIN tbl_vehicles v ON h.vid = v.vid
WHERE h.rn = 1;
或者,使用 MySQL 8 之前的方法:
SELECT h.id, h.vid, h.accnt_id, h.date_online, h.date_offline, v.platenumber
FROM tbl_status_history h
JOIN (
    SELECT vid, GREATEST(MAX(date_offline), MAX(date_online)) max_date
    FROM tbl_status_history
    WHERE accnt_id = 1
    GROUP BY vid
) h2 ON h.vid = h2.vid AND (h.date_offline = h2.max_date OR h.date_online = h2.max_date)
JOIN tbl_vehicles v ON h.vid = v.vid;
你应该考虑更改 tbl_status_history 的结构:
| id | vid | status | date | 
|---|---|---|---|
| 1 | 1 | online | 2023-02-25 | 
| 2 | 1 | offline | 2023-02-26 | 
| 3 | 2 | offline | 2023-02-27 | 
| 4 | 2 | offline | 2023-02-28 | 
| 5 | 1 | offline | 2023-03-01 | 
| 6 | 1 | online | 2023-03-02 | 
accnt_id在tbl_vehicles中,应该在那里,所以这里是多余的。- 使用两个 
DATE列来存储一个状态变更日期是没有意义的。 - 你可以考虑删除 
id,以使用自然键,但我可能不会走那么远。 
英文:
This is one way to produce your "target result" using ROW_NUMBER():
SELECT h.id, h.vid, h.accnt_id, h.date_online, h.date_offline, v.platenumber
FROM (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY vid ORDER BY GREATEST(date_online, date_offline) DESC) rn
    FROM tbl_status_history
    WHERE accnt_id = 1
) h
JOIN tbl_vehicles v ON h.vid = v.vid
WHERE h.rn = 1;
Or, the pre MySQL 8 method:
SELECT h.id, h.vid, h.accnt_id, h.date_online, h.date_offline, v.platenumber
FROM tbl_status_history h
JOIN (
    SELECT vid, GREATEST(MAX(date_offline), MAX(date_online)) max_date
    FROM tbl_status_history
    WHERE accnt_id = 1
    GROUP BY vid
) h2 ON h.vid = h2.vid AND (h.date_offline = h2.max_date OR h.date_online = h2.max_date)
JOIN tbl_vehicles v ON h.vid = v.vid;
You should consider changing the structure of tbl_status_history to:
| id | vid | status | date | 
|---|---|---|---|
| 1 | 1 | online | 2023-02-25 | 
| 2 | 1 | offline | 2023-02-26 | 
| 3 | 2 | offline | 2023-02-27 | 
| 4 | 2 | offline | 2023-02-28 | 
| 5 | 1 | offline | 2023-03-01 | 
| 6 | 1 | online | 2023-03-02 | 
accnt_idis intbl_vehicles, where it belongs, so redundant here- two 
DATEcolumns to store onestatus change datedoes not make sense - you could drop 
idtoo, in favour of the natural key, bit I probably wouldn't go that far 
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论