给出一个带有列
的非常简化的表 Name, Action, Status, Timepoint
1 "A" "Open" "OK" "2012-09-04 10:10:00"
2 "A" "Close" "OK" "2012-09-04 10:05:00"
3 "A" "Close" "ERROR" "2012-09-04 10:02:00"
4 "B" "Look" "NICE" "2012-09-04 10:05:00"
5 "B" "Blow" "COLD" "2012-09-04 10:00:00"
6 "C" "Laugh" "OK" "2012-09-04 10:02:00"
7 "C" "Laugh" "MUTE" "2012-09-04 10:00:00"
如何最有效地为名称和操作的组合选择每一行,但仅限于最新的 Action 的组合时间点? 在上面的例子中,它将返回行
1, 2, 4, 5, 6
工作实现获取行并使用子查询仅在0行具有相同名称,操作更新时间点的组合时才返回。但是,当数据集变大时,这似乎非常低效。就像这样
SELECT Name, Action, Status, Timepoint
FROM foobar
WHERE Name IN (... Names of interest ...) AND
Status IN (... statuses of interest ...) AND
(SELECT COUNT(*) FROM foobar AS t2 WHERE t2.Name = Name AND t2.Status = Status AND t2.Timepoint > Timepoint) = 0
order by Name, Timepoint
答案 0 :(得分:1)
Select *
from
(
select *,
row_number() over (partition by Name, Action order by timepoint desc) RN
from yourtable
) v
where RN = 1
答案 1 :(得分:0)
SELECT Name, Action, Status, MIN(Timepoint)
FROM foobar
WHERE Name IN (... Names of interest ...) AND
Status IN (... statuses of interest ...)
GROUP BY Name, Status, Action
答案 2 :(得分:0)
SELECT Name, Action, Status, TimePoint
FROM foobar f1
JOIN (SELECT Name, Status, MAX(TimePoint) as TimePoint
FROM foobar
GROUP BY Name, Status) f2
ON f1.Name = f2.Name
AND f1.Status = f2.Status
AND f1.TimePoint = f2.TimePoint
答案 3 :(得分:0)
使用ROW_NUMBER隔离所需的行。我喜欢使用只有id的CTE然后再加入原始表。这样,被过滤的行没有那么多的包袱。
-- setup
DECLARE @temp TABLE(id INT,name CHAR(1),Action VARCHAR(5),Status VARCHAR(5),Timepoint DATETIME)
INSERT INTO @temp (id,name,Action,Status,Timepoint)VALUES
(1,'A','Open','OK','2012-09-04 10:10:00')
,(2,'A','Close','OK','2012-09-04 10:05:00')
,(3,'A','Close','ERROR','2012-09-04 10:02:00')
,(4,'B','Look','NICE','2012-09-04 10:05:00')
,(5,'B','Blow','COLD','2012-09-04 10:00:00')
,(6,'C','Laugh','OK','2012-09-04 10:02:00')
,(7,'C','Laugh','MUTE','2012-09-04 10:00:00')
-- solution
;WITH groups AS
(
SELECT
id
, rowNum = ROW_NUMBER() OVER(
PARTITION BY Name,Action
ORDER BY Timepoint DESC)
FROM @temp
)
SELECT temp.id, name, Action, Status, Timepoint
FROM groups INNER JOIN @temp temp ON temp.id = groups.id
WHERE rowNum = 1