SQL 关于从两列中获取具有最大日期的记录的查询

SQL query regarding getting record having maximum date from two columns

我有一个 SQL 服务器 table 是这样的:

EMPs

Id  Name    DateOn              DateOff     
-------------------------------------------------
1   EMP1    2020-9-4 12:00 AM   NULL
2   EMP1    2020-9-4 12:00 AM   2020-9-4 10:00 PM
3   EMP2    2020-7-4 12:00 AM   NULL
4   EMP4    2020-7-4 12:00 AM   2020-9-4 10:00 PM

查询的另一个示例

DECLARE @EMP TABLE
(
    Id INT,
    NAME VARCHAR(200),
    AlarmOnTimeStamp DATETIMEOFFSET,
    AlarmOffTimeStamp DATETIMEOFFSET NULL
);


INSERT INTO @EMP VALUES(1,'Test1','2020-04-09 01:56:29.507',NULL)
INSERT INTO @EMP VALUES(2,'Test1','2020-04-09 01:56:29.507','2020-04-09 03:56:29.507')
INSERT INTO @EMP VALUES(3,'Test2','2020-04-09 01:56:29.507','2020-04-09 03:56:29.507')


select * from (
    select *,
           row_number() over (order by a.AlarmOffTimestamp  desc) rn
    from @EMP a
) a where rn = 1

enter image description here

Id 列是唯一的。

我想要一个 SQL 查询,要像上面的例子一样得到单条记录,我应该得到 Id => 2,3 和第 4 条记录;我很困惑如何将两列最大日期与 group by 语句一起使用。

您可以使用子查询进行过滤:

select e.*
from emps e
where e.id = (
    select top (1) id 
    from emps e1
    where e1.name = e.name 
    order by e1.dateon desc, e1.dateoff desc
)

不是很清楚你想要什么排序标准;这为您提供了具有最新 dateon 的记录;如果有关系,dateoff 用于打破它们。您可能希望根据您的具体要求调整子查询的 order by 子句。

此解决方案通常非常有效,即使是针对大型数据集也是如此。为了提高性能,您需要 (name, dateon, dateoff) 上的索引。您也可以尝试在索引的最后位置添加 id,例如 (name, dateon, dateoff, id):这会使索引 覆盖 ,这意味着数据库可以执行仅通过查看索引的子查询。

Demo on DB Fiddle

示例数据:

Id | NAME  | AlarmOnTimeStamp            | AlarmOffTimeStamp          
-: | :---- | :-------------------------- | :--------------------------
 1 | Test1 | 2020-04-09 01:56:29.5070000 | null                       
 2 | Test1 | 2020-04-09 01:56:29.5070000 | 2020-04-09 03:56:29.5070000
 3 | Test2 | 2020-04-09 01:56:29.5070000 | 2020-04-09 03:56:29.5070000

结果:

Id | NAME  | AlarmOnTimeStamp            | AlarmOffTimeStamp          
-: | :---- | :-------------------------- | :--------------------------
 2 | Test1 | 2020-04-09 01:56:29.5070000 | 2020-04-09 03:56:29.5070000
 3 | Test2 | 2020-04-09 01:56:29.5070000 | 2020-04-09 03:56:29.5070000

我认为简单的 row_number() 函数在这种情况下应该很好:

select * from (
    select *,
           row_number() over (order by DateOff desc) rn
    from myTable
) a where rn = 1

在性能方面,您可以在用于排序和过滤结果集的列上定义索引,在这种情况下 DateOff 用于排序,因此它是索引的良好候选者。