选择具有最早日期的行

时间:2013-10-25 12:02:21

标签: sql sql-server

我有一个查询,其中我为给定的事件返回多行,例如:

ID      |   DateTime                | String

1017436 |   2013-09-13 05:19:20.000 |                 Hello 
1017436 |   2013-09-13 11:49:00.000 |                 World

我希望结果只包含任何给定ID的行的最早次出现,但遇到了麻烦。

我最初认为这样的查询就是答案:

; WITH cte AS
  ( SELECT *,
           rn =  ROW_NUMBER() OVER (PARTITION BY ixBug ORDER BY dt)
    FROM dbo.BugEvent
) 
SELECT ixBug, dt, s
    FROM cte
    WHERE 
        ixBug IN (SELECT Bug.ixBug
                        FROM 
                            dbo.Bug
                                JOIN
                            dbo.Mailbox ON Mailbox.ixMailbox = Bug.ixMailbox
                        WHERE
                                ixBug = '1017436'
                                AND 
                                    YEAR(dtOpened) >= '2013'
                                AND
                                    MONTH(dtOpened) = '09'
                                AND
                                    sOriginalTitle NOT LIKE '\[web\]%' ESCAPE '\'
                                AND 
                                    dbo.Bug.ixProject = (SELECT ixProject
                                                            FROM dbo.Project
                                                            WHERE sProject = 'Support')
                                AND
                                    dbo.Bug.ixCategory = (SELECT ixCategory
                                                            FROM dbo.Category
                                                            WHERE sCategory = '.inquiry')               
                                AND
                                    Bug.ixBug NOT IN(SELECT Bug.ixBug
                                                    FROM 
                                                        dbo.Bug
                                                            JOIN
                                                        dbo.Mailbox ON Mailbox.ixMailbox = Bug.ixMailbox
                                                    WHERE 
                                                                YEAR(dtOpened) >= '2013'
                                                            AND
                                                                MONTH(dtOpened) <= '09'
                                                            AND
                                                                sOriginalTitle LIKE '\[web\]%' ESCAPE '\'
                                                            AND 
                                                                dbo.Bug.ixProject = (SELECT ixProject
                                                                                FROM dbo.Project
                                                                                WHERE sProject = 'Support')
                                                            AND
                                                                dbo.Bug.ixCategory = (SELECT ixCategory
                                                                                        FROM dbo.Category
                                                                                        WHERE sCategory = '.inquiry')))
        AND
            sVerb = 'Incoming Email';

但是,由于某种原因,结果会保留两行。

5 个答案:

答案 0 :(得分:3)

您可以使用窗口函数ROW_NUMBER()MIN()。我们的想法是按ID分配行 - OVER (PARTITION BY id) - 然后分配行号(按日期时间排序)或查找每个ID的最小日期时间。

ROW_NUMBER()的解决方案:

; WITH cte AS
  ( SELECT id, datetime, string,
           rn =  ROW_NUMBER() OVER (PARTITION BY id ORDER BY datetime)
    FROM tableX
  ) 
SELECT id, datetime, string
FROM cte
WHERE rn = 1 ;   

MIN()

; WITH cte AS
  ( SELECT id, datetime, string,
           min_datetime =  MIN(datetime) OVER (PARTITION BY id)
    FROM tableX
  ) 
SELECT id, datetime, string
FROM cte
WHERE datetime = min_datetime ;   

第二个版本的行为略有不同。如果有两个(或更多)行具有完全相同的ID日期时间,则它们将同时出现在结果中。

答案 1 :(得分:1)

您可以使用ROW_NUMBER()生成可以过滤的序号。

SELECT  ID, DateTime, String
FROM    
        (
            SELECT  ID, DateTime, String,
                    ROW_NUMBER() OVER (PARTITION BY ID ORDER BY DateTime) RN
            FROM    tableName
        ) a
WHERE   RN = 1

答案 2 :(得分:1)

在公用表表达式CTE中选择每个ID的最小日期,然后再加入它。

with minDates (id, date)
as
(
     select id, min(date) as date from YourTable
     group by id

)

select yt.*
from YourTable yt
inner join minDates md on yt.id = md.id and yt.date = md.date

答案 3 :(得分:1)

select top 1 id, date_time, string
from table
where id = ?
order by date_time

答案 4 :(得分:0)

Select
  ID
, DateTime
, String
From MyTable t1
Where t1.DateTime =
(
    Select Min(t2.DateTime)
    From MyTable t2
    Where td.ID = t1.ID
)

使用子查询获取每个ID组的最小日期时间,然后使用该子查询来限定您提取的ID。如果是平局,你会得到两者。如果ID是按时间顺序排列的,则可以通过使用ID而不是DateTime作为选择器来避免这种情况。