我试图避免使用循环来获得此解决方案的冲动,而是使用基于集合的操作。
我需要根据最近出现的连接到另一个表来更新表中的每条记录。我的第一个想法是加入我需要"最近的约会"来自和加入条件的分组,但使用GROUP BY
与UPDATE
无效。
这是我到目前为止所拥有的。我有一种感觉,这将通过CTE来解决......
CREATE TABLE Part (
Area VARCHAR(10) NOT NULL,
SequenceNumber INT NOT NULL,
DateAdded DATETIME NOT NULL
);
INSERT INTO Part VALUES
('A', 1, '2018-04-01'),
('A', 1, '2018-04-02'),
('A', 2, '2018-04-03'),
('A', 2, '2018-04-04'),
('B', 2, '2018-04-04'),
('B', 2, '2018-04-03'),
('B', 3, '2018-04-02'),
('B', 3, '2018-04-01');
DECLARE @Filters TABLE
(
Area VARCHAR(10),
StartingSeqNum INT,
StartTime DATETIME
);
INSERT INTO @Filters VALUES
('A', 2, NULL),
('B', 3, NULL);
-- Update each StartTime in @Filters with the most recent
-- DateAdded of the corresponding SequenceNumber in the Part table per Area.
UPDATE f
SET f.StartTime = MAX(p.DateAdded)
FROM
@Filters f
INNER JOIN Part p ON p.Area = f.Area
AND p.SequenceNumber = f.StartingSeqNum
GROUP BY
p.Area,
p.SequenceNumber;
根据上面的示例数据,操作应填充@Filters
中的以下值:
('A', 2, '2018-04-04')
('B', 3, '2018-04-02')
答案 0 :(得分:2)
您可以使用CTE执行此操作,如下所示:
;with maxParts as
(
select Area, SequenceNumber, MAX(dateadded) as maxDateAdded
from Part
group by Area, SequenceNumber
)
UPDATE f
SET f.StartTime = p.maxDateAdded
from @Filters f
inner join maxParts p
on f.Area = p.Area
and f.StartingSeqNum = p.SequenceNumber
但是,您也可以将CTE重写为子查询:
UPDATE f
SET f.StartTime = p.maxDateAdded
from @Filters f
inner join (
select Area, SequenceNumber, MAX(dateadded) as maxDateAdded
from Part
group by Area, SequenceNumber
) p
on f.Area = p.Area
and f.StartingSeqNum = p.SequenceNumber
这些的查询计划应该是相同的 - 所有CTE确实允许您查看更清晰的查询以及轻松重用该SELECT的能力。
答案 1 :(得分:1)
(a)中
UPDATE Filters
SET Filters.StartTime = (SELECT max(Part.DateAdded)
FROM Part
WHERE Part.Area = Filters.Area
AND Part.SequenceNumber = Filters.StartingSeqNum)
FROM @Filters Filters;
(b)中
UPDATE Filters
SET Filters.StartTime = X.StartTime
FROM @Filters Filters
INNER JOIN (SELECT max(Part.DateAdded) StartTime,
Part.Area,
Part.SequenceNumber
FROM Part
GROUP BY Part.Area,
Part.SequenceNumber) X
ON X.Area = Filters.Area
AND X.SequenceNumber = Filters.StartingSeqNum;
两者,(a)和(b)应该做你想要的。我不确定什么更好。也许(b)可以重用子查询关系,因此整体成本较低。