请复制并运行以下脚本
DECLARE @Customers TABLE (CustomerId INT)
DECLARE @Orders TABLE ( OrderId INT, CustomerId INT, OrderDate DATETIME )
DECLARE @Calls TABLE (CallId INT, CallTime DATETIME, CallToId INT, OrderId INT)
-----------------------------------------------------------------
INSERT INTO @Customers SELECT 1
INSERT INTO @Customers SELECT 2
INSERT INTO @Customers SELECT 3
-----------------------------------------------------------------
INSERT INTO @Orders SELECT 10, 1, DATEADD(d, -20, GETDATE())
INSERT INTO @Orders SELECT 11, 1, DATEADD(d, -10, GETDATE())
INSERT INTO @Orders SELECT 12, 2, DATEADD(d, -8, GETDATE())
INSERT INTO @Orders SELECT 13, 2, DATEADD(d, -6, GETDATE())
INSERT INTO @Orders SELECT 14, 3, DATEADD(d, -4, GETDATE())
-----------------------------------------------------------------
INSERT INTO @Calls SELECT 101, DATEADD(d, -19, GETDATE()), 1, NULL
INSERT INTO @Calls SELECT 102, DATEADD(d, -17, GETDATE()), 1, NULL
INSERT INTO @Calls SELECT 103, DATEADD(d, -9, GETDATE()), 1, NULL
INSERT INTO @Calls SELECT 104, DATEADD(d, -6, GETDATE()), 1, NULL
INSERT INTO @Calls SELECT 105, DATEADD(d, -5, GETDATE()), 1, NULL
INSERT INTO @Calls SELECT 106, DATEADD(d, -4, GETDATE()), 2, NULL
INSERT INTO @Calls SELECT 107, DATEADD(d, -2, GETDATE()), 2, NULL
INSERT INTO @Calls SELECT 108, DATEADD(d, -2, GETDATE()), 3, NULL
我想更新@Calls表并需要以下结果。
我使用以下查询(回答之前的旧查询)
UPDATE @Calls
SET OrderId = (
CASE
WHEN (s.CallTime > e.OrderDate)
THEN e.OrderId
END
)
FROM @Calls s INNER JOIN @Orders e ON s.CallToId = e.CustomerId
修改 现在我正在使用此查询
UPDATE c set OrderID = o1.OrderID
from @Calls c inner join @Orders o1 on c.CallTime > o1.OrderDate
left join @Orders o2 on c.CallTime > o2.OrderDate
and o2.OrderDate > o1.OrderDate
where o2.OrderID is null
and o1.CustomerId = c.CallToId
我的查询结果不是我需要的。
要求:
如你所见,有两个订单。一个在2010-12-12
,一个在2010-12-22
。我想更新@Calls
表,其中包含与CallTime相关的OrderId。
简而言之如果添加了后续订单,并且还有其他呼叫,那么我们假设新呼叫与最近的订单相关
注意: 这是样本数据,因此我不总是有两个订单。可能有10多个订单和100多个电话以及1000个客户。
注2 我找不到这个问题的好标题。如果你想的更好,请改变它。
EDIT2: 答案中提供的查询花费了太多时间。要更新的记录总数约为250000。
感谢。
答案 0 :(得分:5)
您可以使用左连接来检查“不受欢迎”的行,并在WHERE
子句中删除它们:
UPDATE c set OrderID = o1.OrderID
from @Calls c
inner join
@Orders o1
on
c.CallTime > o1.OrderDate
left join
@Orders o2
on
c.CallTime > o2.OrderDate and
o2.OrderDate > o1.OrderDate
where
o2.OrderID is null
select * from @Calls
即。首先使用常规连接设置查询 - 您希望在调用(c)之前找到订单(o1)中的行。但是这可以返回多行(如果在调用之前发生多个行(c)。那么你执行另一个连接到命令(o2)寻找在(o1)中找到的行之后出现的行,但是仍然在调用之前(c)。如果我们可以进行这样的匹配,那么我们毕竟不需要那个(o1)行。所以我们在WHERE子句中过滤掉那个组合的行。
现在您已经添加了CustomerID,您还需要考虑在您的加入条件中 - 左连接到@Orders(o2)将会找到任何以后的调用,而不仅仅是同一个客户的调用。要保持两个连接之间的对称性:
UPDATE c set OrderID = o1.OrderID
from @Calls c
inner join
@Orders o1
on
c.CallTime > o1.OrderDate
and c.CallToID = o1.CustomerId /* <-- New line 1 */
left join
@Orders o2
on
c.CallTime > o2.OrderDate and
o2.OrderDate > o1.OrderDate
and c.CallToID = o2.CustomerId /* <-- New line 2 */
where
o2.OrderID is null
这也有望解决一些性能问题。