0

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

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';

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

4

5 回答 5

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 有两个(或更多)行具有完全相同的日期时间,则它们都将出现在结果中。

于 2013-10-25T12:07:01.600 回答
1

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

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
于 2013-10-25T12:04:41.887 回答
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
于 2013-10-25T12:06:21.873 回答
1
select top 1 id, date_time, string
from table
where id = ?
order by date_time
于 2013-10-25T12:07:08.130 回答
0
Select
  ID
, DateTime
, String
From MyTable t1
Where t1.DateTime =
(
    Select Min(t2.DateTime)
    From MyTable t2
    Where td.ID = t1.ID
)

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

于 2013-10-25T12:21:25.693 回答