2012-09-04 41 views
0

给出一个非常简单的表列选择行,但只有最新的时间戳

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" 

如何最有效地选择每一行的名称行动但组合只有动作最新时间点? 在上面的例子中,它将返回行

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 

回答

1
Select * 
from 
(
     select *, 
      row_number() over (partition by Name, Action order by timepoint desc) RN 
     from yourtable 
) v 
where RN = 1 
+0

像魅力一样工作 – inquam

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 
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 
+0

如果时间点重复,这可能会返回重复的行。 –

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