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"

如何最有效地为NameAction组合选择每一行,但只选择最新Timepoint的Action?在上面的示例中,它将返回行

1, 2, 4, 5, 6

工作实现获取行并使用子查询仅在有 0 行具有相同NameAction组合的较新Timepoint时才返回。但是当数据集变得很大时,这似乎非常低效。是这样的

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
4

4 回答 4

1
Select *
from 
(
      select *,
             row_number() over (partition by Name, Action order by timepoint desc) RN
      from yourtable
) v
where RN = 1
于 2012-09-04T11:11:54.460 回答
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
于 2012-09-04T11:12:53.527 回答
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
于 2012-09-04T11:16:54.993 回答
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
于 2012-09-04T11:26:01.017 回答