【发布时间】:2015-09-04 19:09:05
【问题描述】:
我有严重的脑胀气。
为了简单起见,我有 3 个表:Orders、Statuses、XrefOrdersStatuses
我已经设置了一个 SQLFiddle (SQLFiddle Here),其中包含简化的架构和一些经过编辑的行数据。
我需要获得的是带有最新 XrefOrdersStatuses(与 Statuses 结合)的订单。我可以使用以下查询来做到这一点:
SELECT o.shopper_name_first, o.shopper_name_last, os.os_name, x.xos_order_id, x.xos_status_id, x.xos_datetime
FROM Orders AS o
INNER JOIN XrefOrdersStatuses AS x ON x.xos_order_id = o.order_id
LEFT JOIN Statuses AS os ON os.os_id = x.xos_status_id
ORDER BY x.xos_order_id, x.xos_datetime DESC
结果如下:
| shopper_name_first | shopper_name_last | os_name | xos_order_id | xos_status_id | xos_datetime |
|--------------------|-------------------|---------------------|--------------|---------------|------------------------|
| Sally | Sue | Order Pre-Processed | 34049 | 31 | June, 18 2015 12:42:50 |
| Sally | Sue | Order Paid | 34049 | 20 | June, 18 2015 12:36:30 |
| Sally | Sue | Order Created | 34049 | 10 | June, 18 2015 12:34:56 |
| Joe | Schmoe | Order Pre-Processed | 34050 | 31 | June, 18 2015 12:54:50 |
| Joe | Schmoe | Order Paid | 34050 | 20 | June, 18 2015 12:38:30 |
| Joe | Schmoe | Order Created | 34050 | 10 | June, 18 2015 12:34:56 |
| Peter | Piper | Order Paid | 34051 | 20 | June, 18 2015 12:37:30 |
| Peter | Piper | Order Created | 34051 | 10 | June, 18 2015 12:34:56 |
在生产场景中,我选择(ing)更多/所有 Orders 表列,为了简单起见,将它们留在这里。注意重复的订单,但状态是一致的。
在我看来,我正在努力的目的不是找到最新的状态。此视图列出了订单,我想根据最大日期时间列值将每个订单与其各自的最新状态连接/匹配。一对多模式(一个订单有多个状态)。
所以我想做的是:
- 选择订单
- 使用 MAX(xos_datetime) GROUP BY xos_order_id 加入外部参照
- 加入状态以获取定义
订单必须保留在查询中的左侧表(对于与其他表一起使用的其他连接)。在经历了许多其他 SO 问题和答案以及许多 Google 搜索之后,我还没有完全找到我需要的东西。
如果需要按最大日期时间获取 XrefOrdersStatuses 并按订单 ID 分组,这将是查询......
SELECT x.*
FROM XrefOrdersStatuses AS x
JOIN (
SELECT xos_order_id, MAX(xos_datetime) AS maxdate
FROM XrefOrdersStatuses
GROUP BY xos_order_id
) AS x1 ON x1.xos_order_id = x.xos_order_id AND x1.maxdate = x.xos_datetime;
导致:
| xos_id | xos_order_id | xos_status_id | xos_datetime |
|--------|--------------|---------------|------------------------|
| 118287 | 34051 | 20 | June, 18 2015 12:37:30 |
| 118289 | 34049 | 31 | June, 18 2015 12:42:50 |
| 118290 | 34050 | 31 | June, 18 2015 12:54:50 |
...耶!每个订单的最新状态!
唉,我需要 Orders 表作为左侧表(其他连接和搜索位置 - 即名称、活动/非活动、分配给用户等)。
我的麻烦是将 Orders 查询与 XrefOrdersStatuses 查询结合起来。我只是似乎不能让他们一起玩。我的尝试因排序、分组以及各种激烈的混乱而失败。
我觉得这让我很接近,但是让分组和排序正确是我发泄的地方:
SELECT o.shopper_name_first, o.shopper_name_last, os.os_name, x.xos_order_id, x.xos_status_id, x.xos_datetime
FROM Orders AS o
JOIN (
SELECT xz.*
FROM XrefOrdersStatuses AS xz
JOIN (
SELECT xos_order_id, MAX(xos_datetime) AS maxdate
FROM XrefOrdersStatuses
GROUP BY xos_order_id
) AS x1 ON x1.xos_order_id = xz.xos_order_id AND x1.maxdate = xz.xos_datetime
) AS x
LEFT JOIN Statuses AS os ON os.os_id = x.xos_status_id
ORDER BY x.xos_order_id, x.xos_datetime DESC;
结果如下所示:
| shopper_name_first | shopper_name_last | os_name | xos_order_id | xos_status_id | xos_datetime |
|--------------------|-------------------|---------------------|--------------|---------------|------------------------|
| Joe | Schmoe | Order Pre-Processed | 34049 | 31 | June, 18 2015 12:42:50 |
| Peter | Piper | Order Pre-Processed | 34049 | 31 | June, 18 2015 12:42:50 |
| Sally | Sue | Order Pre-Processed | 34049 | 31 | June, 18 2015 12:42:50 |
| Joe | Schmoe | Order Pre-Processed | 34050 | 31 | June, 18 2015 12:54:50 |
| Peter | Piper | Order Pre-Processed | 34050 | 31 | June, 18 2015 12:54:50 |
| Sally | Sue | Order Pre-Processed | 34050 | 31 | June, 18 2015 12:54:50 |
| Peter | Piper | Order Paid | 34051 | 20 | June, 18 2015 12:37:30 |
| Sally | Sue | Order Paid | 34051 | 20 | June, 18 2015 12:37:30 |
| Joe | Schmoe | Order Paid | 34051 | 20 | June, 18 2015 12:37:30 |
我尝试了不同的变化,尝试向前、向后、向左、向右、向内、向外、向上、向下、热、冷、湿、干......你明白了。
我需要的是它看起来像这样:
| shopper_name_first | shopper_name_last | os_name | xos_order_id | xos_status_id | xos_datetime |
|--------------------|-------------------|---------------------|--------------|---------------|------------------------|
| Sally | Sue | Order Pre-Processed | 34049 | 31 | June, 18 2015 12:42:50 |
| Joe | Schmoe | Order Pre-Processed | 34050 | 31 | June, 18 2015 12:54:50 |
| Peter | Piper | Order Paid | 34051 | 20 | June, 18 2015 12:37:30 |
如果您返回第一个查询...我需要这些结果,但会减少,以便只保留每个订单的最新状态。事实上,我实际上是在 PHP 中这样做的......因此我正在重新访问查询以从 PHP 中删除看似不必要的步骤。
也许我的解决方案是 XrefOrdersStatuses 查询(上面的第二个),但使用 RIGHT JOIN 来获取 Order 和 Status 表?
有人想吗?很抱歉让这个问题这么长(几乎是 TL;我自己的 DR),但我希望我已经适当地注释了这个问题。
顺便说一句——我是 SO 的长期潜伏者(从这里发现的问题中收集了无数的问题和提示!)但这是我第一次陷入困境并且无法弄清楚如何获得我需要什么。
编辑/回答:按照我需要的方式设置查询,发现我的性能问题与列和索引有关。有点像因为腹痛去医院,结果被告知您患有克罗恩病,然后发现您的肾脏长了一个肿瘤——最后一切都好起来了。
# Query for answer to user Linoff with mods
SELECT o.shopper_name_first, o.shopper_name_last, s.os_name, x.*
FROM Orders o
RIGHT JOIN XrefOrdersStatuses x ON x.xos_order_id = o.order_id
RIGHT JOIN
(
SELECT xos_order_id, MAX(xos_datetime) AS maxdate
FROM XrefOrdersStatuses
GROUP BY xos_order_id
) xmax ON xmax.xos_order_id = x.xos_order_id AND xmax.maxdate = x.xos_datetime
LEFT JOIN Statuses s ON s.os_id = x.xos_status_id
ORDER BY o.order_datetime DESC;
【问题讨论】:
标签: mysql datetime join group-by