比使用"A UNION(B in A)"更高效的SQL?

mac*_*tus 5 sql union where

编辑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');

mac*_*tus 0

再次感谢您的所有建议。我找到了三个有效的解决方案,包括我原来的解决方案。最后我添加了一些性能结果,但没有我希望的那么好。如果有人能改进这一点,我会很高兴!

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 秒