从客户订单表中查找最近的订单副本 - SLOW CROSS APPLY

时间:2021-06-16 17:37:01

标签: sql sql-server ssms

我只想显示客户订购了完全相同商品的订单,但只显示之前下过的最近完成的订单。

我希望为同一客户、同一商品获得最直接的订单。喜欢显示重复的,但只是最近的。

查询可以很好地完成我想要它做的事情,但是当我将交叉应用添加到我的实际查询时,它会减慢很多。

编辑:我也试过选择前 1,而不是使用行号。 rownumber 行使其仅快 1 秒。

declare @orders as table (
    ord_id numeric(7,0),
    customer_id numeric(4,0),
    order_time datetime,
    item_id numeric (4,0),
    status int NOT NULL
)

insert into @orders values
(1516235,5116,'06/04/2021 11:06:00', 5616, 1),
(1516236,5116,'06/03/2021 13:51:00', 5616, 1),
(1514586,5554,'06/01/2021 08:16:00', 5616, 1),
(1516288,5554,'06/01/2021 15:35:00', 5616, 1),
(1516241,5554,'06/04/2021 11:11:00', 4862, 1),
(1516778,5554,'06/04/2021 11:05:00', 4862, 2)

select distinct *
from @orders o
cross apply (
    select a.ord_id, row_number() over (partition by a.customer_id order by a.order_time) as rownum
    from @orders a 
    where a.customer_id = o.customer_id and
    a.status != 2 and
    a.item_id = o.item_id and
    a.order_time < o.order_time
)a

where a.rownum = 1

还有其他方法可以做到这一点吗?我怎样才能加快速度?

之前的订单必须有

  1. 其他订单之前的订单时间
  2. 相同的客户记录
  3. 相同的商品记录
  4. 之前所有其他记录中的最新记录
  5. 取消的状态(1 = 完成;2 = 取消)

1 个答案:

答案 0 :(得分:1)

那是愚蠢的。这是使用 cross apply 的更简单方法:

select o.*
from @orders o cross apply
     (select top (1) a.ord_id
      from @orders a 
      where a.customer_id = o.customer_id and
            a.status <> 2 and
            a.item_id = o.item_id and
            a.order_time < o.order_time
      order by a.order_time
     ) a;

这可以使用 (customer_id, item_id, status, order_time) 上的索引。

注意:如果您想要最近的前一个订单,则 order by 应使用 desc。但是,问题中的代码并非如此。

而且,您应该能够使用窗口函数。如果 ord_id 随时间增加:

min(case when status <> 2 then ord_id end) over (partition by customer_id, item_id)

即使这不是真的,也有变化,但由于状态过滤,它更复杂(即需要子查询)。

相关问题