5

编辑1(澄清):感谢您到目前为止的回答!反应令人欣慰。
我想稍微澄清一下这个问题,因为根据答案,我认为我没有正确描述问题的一个方面(我确信这是我的错,因为我很难为自己定义它)。
这就是问题所在:结果集应该只包含 tstamp BETWEEN '2010-01-03' AND '2010-01-09' 的记录,以及第一组中每个 order_num 的 tstamp 为 NULL 的记录(会有对于每个 order_num,始终为 1,且 tstamp 为空)。
到目前为止给出的答案似乎包括某个 order_num 的所有记录(如果有的话)带有“2010-01-03”和“2010-01-09”之间的时间戳。例如,如果有另一条记录 order_num = 2 且 tstamp = 2010-01-12 00:00:00,则不应将其包含在结果中。

原始问题:
考虑一个包含 id(唯一)、order_num、tstamp(时间戳)和 item_id(订单中包含的单个项目)的订单表。tstamp 为空,除非订单已被修改,在这种情况下,会有另一条具有相同 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,其中至少一个 order_num 的 tstamp NOT NULL AND 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)”,但是执行起来很慢,希望有更高效的解决方案:

选择 history_orders.order_id、history_orders.tstamp、history_orders.item_id
从
   (选择 orders.order_id、orders.tstamp、orders.item_id
    来自订单
    WHERE orders.tstamp BETWEEN '2010-01-03' AND '2010-01-09')
    作为历史订单
联盟
选择 current_orders.order_id、current_orders.tstamp、current_orders.item_id
从
   (选择 orders.order_id、orders.tstamp、orders.item_id
    来自订单
    订单.tstamp 为空)
    作为 current_orders
在哪里 current_orders.order_id IN
   (选择订单.order_id
    来自订单
    WHERE orders.tstamp BETWEEN '2010-01-03' AND '2010-01-09');
4

6 回答 6

3

也许是一个子查询:

select * from order o where o.order_num in (select distinct
  order_num from order where tstamp between '2010-01-03' and '2010-01-09')
于 2010-01-22T21:30:41.703 回答
1

除非我误解了,否则这样的事情应该可以解决问题:

SELECT o1.id, o1.order_num, o.tstamp, o.item_id
FROM  orders o1
WHERE EXISTS(
    SELECT * FROM orders o2 
    WHERE o1.order_num = o2.order_num 
        AND o2.tstamp BETWEEN '2010-01-03' AND '2010-01-09')

使用 EXISTS 的好处是它会在第一次匹配时停止。

于 2010-01-22T21:33:58.453 回答
1

我知道回复已经很晚了,但我刚刚看到这个帖子,我想也许我应该尝试一次,这个查询怎么样,与上述所有解决方案相比,它真的非常小并且解决了目的。

select * from orders_gc where order_num in 
    (select order_num
     from orders_gc 
     group by order_num 
     having count(id) > 1 and 
     MAX(tstamp) between '03-jan-2010' and '09-jan-2010')
于 2010-05-21T09:19:10.427 回答
0

您可以自行加入表。简化后,这看起来像:

select order_id
from orders all_orders
inner join orders not_null_orders
    on all_orders.order_id = not_null_orders.order_id
where
    not_null_orders.tstamp is not null
    and all_orders.tstamp between '2010-01-03' AND '2010-01-09'
于 2010-01-22T21:35:53.373 回答
0

希望我的问题是正确的。这应该返回在提供的时间戳内已更改的所有订单。

SELECT o.order_id, o.tstamp, o.item_id
FROM orders o
JOIN ( SELECT DISTINCT o2.order_num
       FROM orders o2
       WHERE o2.tstamp BETWEEN '2010-01-03' AND '2010-01-09' ) o3
ON ( o3.order_num = o.order_num )
于 2010-01-22T21:34:13.710 回答
0

再次感谢您的所有建议。我找到了三种可行的解决方案,包括我的原始解决方案。最后,我添加了一些性能结果,但并没有我希望的那么好。如果有人可以改进这一点,我会很激动!

1)迄今为止发现的最佳解决方案似乎是:

选择 history_orders.order_id、history_orders.tstamp、history_orders.item_id
从
   (选择 orders.order_id、orders.tstamp、orders.item_id
    来自订单
    WHERE orders.tstamp BETWEEN '2010-01-03' AND '2010-01-09'
    或 orders.tstamp 为空)
    作为历史订单
在哪里 history_orders.order_id IN
   (选择订单.order_id
    来自订单
    WHERE orders.tstamp BETWEEN '2010-01-03' AND '2010-01-09');

2)我还尝试使用 EXISTS 代替 IN,这需要在最后一个 SELECT 中添加一个额外的 WHERE 子句:

选择 history_orders.order_id、history_orders.tstamp、history_orders.item_id
从
   (选择 orders.order_id、orders.tstamp、orders.item_id
    来自订单
    WHERE orders.tstamp BETWEEN '2010-01-03' AND '2010-01-09'
    或 orders.tstamp 为空)
    作为历史订单
存在于何处
   (选择订单.order_id
    来自订单
    WHERE history_orders.order_id = orders.order_id
    AND orders.tstamp BETWEEN '2010-01-03' AND '2010-01-09');

3) 最后是我原来的解决方案,使用 UNION。

评论:
为了评论表的大小,我实际的“真实世界”问题涉及 4 个表(通过内部连接连接),分别包含 98、2189、43897、785656 条记录。

性能 - 每个解决方案我运行了 3 次,这是我的真实世界结果:
1:52、51、51 秒
2:54、54、53 秒
3:56、56、56 秒

于 2010-01-25T16:10:13.197 回答