编辑1(澄清):感谢您到目前为止的答案!回应令人满意.
我想稍微澄清一下这个问题,因为根据答案,我认为我没有正确描述问题的一个方面(而且我确信这是我的错,因为即使是我自己也很难定义它).
这里的难题是:结果集应该只包含与BETWEEN"2010-01-03" TSTAMP的记录和"2010-01-09",以及一个记录,其中TSTAMP IS NULL在第一组中的每个order_num(会有对于每个order_num,总是一个null tstamp).
到目前为止给出的答案似乎包括某个order_num的所有记录(如果有的话)与tstamp BETWEEN'2010-01-03'和'2010-01-09'.例如,如果存在与order_num = 2和TSTAMP另一个记录= 2010-01-12 00:00:00它应该不被包含在结果中.
原始问题:
考虑包含id(唯一),order_num,tstamp(时间戳)和item_id(订单中包含的单个项目)的订单表.除非订单已被修改,否则tstamp为null,在这种情况下,存在具有相同order_num的另一个记录,然后tstamp包含更改发生时的时间戳.
例...
id order_num tstamp item_id __ _________ ___________________ _______ 0 1 100 1 2 101 2 2 2010-01-05 12:34:56 102 3 3 113 4 4 124 5 5 135 6 5 2010-01-07 01:23:45 136 7 5 2010-01-07 02:46:00 137 8 6 100 9 6 2010-01-13 08:33:55 105
检索在特定日期范围内被修改过一次或多次的所有订单(基于order_num)的最有效的SQL语句是什么?换句话说,对于每个订单,我们需要具有相同order_num的所有记录(包括具有NULL tstamp的那个),对于每个order_num,WHERE中至少有一个order_num具有tstamp NOT NULL和tstamp BETWEEN'2010-01-03'和'2010-01-09'.这是"我们遇到困难时,至少有一个order_num具有tstamp NOT NULL".
结果集应如下所示:
id order_num tstamp item_id __ _________ ___________________ _______ 1 2 101 2 2 2010-01-05 12:34:56 102 5 5 135 6 5 2010-01-07 01:23:45 136 7 5 2010-01-07 02:46:00 137
我想出的SQL就是这个,它本质上是"A UNION(B in A)",但它执行起来很慢,我希望有一个更有效的解决方案:
SELECT history_orders.order_id, history_orders.tstamp, history_orders.item_id
FROM
(SELECT orders.order_id, orders.tstamp, orders.item_id
FROM orders
WHERE orders.tstamp BETWEEN '2010-01-03' AND '2010-01-09')
AS history_orders
UNION
SELECT current_orders.order_id, current_orders.tstamp, current_orders.item_id
FROM
(SELECT orders.order_id, orders.tstamp, orders.item_id
FROM orders
WHERE orders.tstamp IS NULL)
AS current_orders
WHERE current_orders.order_id IN
(SELECT orders.order_id
FROM orders
WHERE orders.tstamp BETWEEN '2010-01-03' AND '2010-01-09');
再次感谢您的所有建议。我找到了三个有效的解决方案,包括我原来的解决方案。最后我添加了一些性能结果,但没有我希望的那么好。如果有人能改进这一点,我会很高兴!
1)到目前为止找到的最佳解决方案似乎是:
选择history_orders.order_id、history_orders.tstamp、history_orders.item_id
从
(选择订单.order_id、订单.tstamp、订单.item_id
来自订单
WHERE order.tstamp 介于“2010-01-03”和“2010-01-09”之间
或orders.tstamp为NULL)
AS历史订单
WHERE History_orders.order_id IN
(选择订单.order_id
来自订单
WHERE orders.tstamp 介于“2010-01-03”和“2010-01-09”之间);
2)我还尝试使用 EXISTS 代替 IN,这需要在最后一个 SELECT 中添加一个额外的 WHERE 子句:
选择history_orders.order_id、history_orders.tstamp、history_orders.item_id
从
(选择订单.order_id、订单.tstamp、订单.item_id
来自订单
WHERE order.tstamp 介于“2010-01-03”和“2010-01-09”之间
或orders.tstamp为NULL)
AS历史订单
存在于何处
(选择订单.order_id
来自订单
其中history_orders.order_id =orders.order_id
AND orders.tstamp 介于“2010-01-03”和“2010-01-09”之间);
3)最后是我原来的解决方案,使用UNION。
评论:
要评论表大小,我实际的“现实世界”问题涉及 4 个表(通过内连接连接),分别包含 98、2189、43897、785656 条记录。
性能 - 我将每个解决方案运行了三次,这是我的真实结果:
1: 52, 51, 51 秒
2: 54, 54, 53 秒
3: 56, 56, 56 秒
| 归档时间: |
|
| 查看次数: |
1300 次 |
| 最近记录: |