尝试获取相关货件的最新状态,但我收到的结果不正确
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
)
此查询假设 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 别名的使用,以便查询更易于编写和阅读。
我目前正在做一个项目,同时试图学习 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
)
此查询假设 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 别名的使用,以便查询更易于编写和阅读。