Please copy and run following script
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())
------------------------------------------开发者_Python百科-----------------------
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
I want to update @Calls table and need following results.
I am using the following query (Old query before answer)
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
Edit: Now I am using this query
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
and the result of my query is not what I need.
Requirement:
As you can see there are two orders. One is on 2010-12-12
and one is on 2010-12-22
. I want to update @Calls
table with relevant OrderId with respect to CallTime.
In short If subsequent Orders are added, and there are further calls then we assume that a new call is associated with the most recent Order
Note: This is sample data so this is not the case that I always have two Orders. There might be 10+ Orders and 100+ calls and 1000s of Customers.
Note2 I could not find good title for this question. Please change it if you think of any better.
Edit2: The query provided in answer is taking too much time. Total number of records to update is around 250000.
Thanks.
You can use a left join to check for "undesirable" rows, and eliminate them in your WHERE
clause:
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
I.e. you first set up your query using normal joins - you want to find the row in orders (o1) which occurs before the call (c). But this can return multiple rows (if more than one occurs before the call (c). So you perform another join to orders (o2) seeking rows which occur after the row found in (o1), but still before the call (c). If we can make such a match, then we didn't want that (o1) row after all. So we filter that combined row out in the WHERE clause.
Now that you've added CustomerID, you need to consider that in your join conditions also - that left join to @Orders (o2) is going to find any later call, not just one for the same customer. To keep the symmetry between the two joins to orders:
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
This will also hopefully address some of the performance difficulties.
精彩评论