尝试获取相关货件的最新状态,但我收到的结果不正确

Trying to get latest status for related shipment but the results I receive are incorrect

我目前正在做一个项目,同时试图学习 MySQL,我想加入三个 table 并获取每个相关货件的最新状态。这是我正在使用的 tables(带有示例数据):

出货量

id consignee tracking_number shipper weight import_no
1 JOHN BROWN TBA99900000121 AMAZON 1 101
2 HELEN SMITH TBA99900000190 AMAZON 1 102
3 JACK BLACK TBA99900000123 AMAZON 1 103
4 JOE BROWM TBA99900000812 AMAZON 1 104
5 JULIA KERR TBA99900000904 AMAZON 1 105

状态

id name slug
1 At Warehouse at_warehouse
2 Ready For Pickup ready_for_pickup
3 Delivered delivered

shipment_status(枢轴table)

id shipment_id status_id
1 1 1
2 2 1
3 3 1
4 4 1
5 5 1
6 1 2
7 2 2
8 3 2
9 4 2
10 5 2

所有 table 都有 created_at 和 updated_at 时间戳列

我试图实现的结果示例

slug shipment_id status_id
ready_for_pickup 1 2
ready_for_pickup 2 2
ready_for_pickup 3 2
ready_for_pickup 4 2
ready_for_pickup 5 2

这是我根据过去几天所做的示例和研究编写的查询,旨在尝试实现我正在寻找的内容。我发现有时与发货相关的最新状态有时不匹配

SELECT
  statuses.slug AS slug,
  MAX(shipments.id) AS shipment_id,
  statuses.id AS status_id,
FROM
  `shipments`
     INNER JOIN `shipment_status` ON `shipment_status`.`shipment_id` = `shipments`.`id`
     INNER JOIN `statuses` ON `shipment_status`.`status_id` = `statuses`.`id`
     GROUP BY
       `shipment_id`

因为我们需要引用从 MAX 聚合计算的同一记录中的其他字段,你需要分两步完成,还有其他方法,但我发现这个语法更简单:

SELECT
  shipments.id AS id,
  statuses.slug AS slug,
  statuses.id AS status_id,
  shipment_status.shipment_id as shipment_id
FROM
  `shipments`
     INNER JOIN `shipment_status` ON `shipment_status`.`shipment_id` = `shipments`.`id`
     INNER JOIN `statuses` ON `shipment_status`.`status_id` = `statuses`.`id`
WHERE 
   shipment_status.id = (
       SELECT MAX(shipment_status.id)
       FROM `shipment_status`
       WHERE shipment_status.shipment_id = shipments.id
   )

try it out!

此查询假设 id 字段是标识列,因此 MAX(shipment_status.id) 仅代表给定 shipment_id[= 的最新 status 16=]

您可以使用 window 函数:

SELECT s.id, st.slug, st.id
FROM shipments s JOIN
     (SELECT ss.*,
             ROW_NUMBER() OVER (PARTITION BY shipment_id ORDER BY ss.id DESC) as seqnum
      FROM shipment_status ss
     ) ss
     ON ss.shipment_id = s.id JOIN
     statuses st
     ON ss.status_id` = st.id
WHERE ss.seqnum = 1;

另请注意 table 别名的使用,以便查询更易于编写和阅读。