Sql 组内日期选择

Sql 组内日期选择,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有一个表,它有两个日期列,并以下面的方式比较日期,这样date1应该小于date2,但date1应该是其组中的最新日期 我可以得到我想要的结果,但问题是,这可能不是最好的方法,因为在我的原始表中,我有数百万条记录和大约30-40列 因此,在编写select时,我将使用max(col1)、max(col2)、…max(col40),这将非常繁琐,而且不是正确的方法,我想知道是否有更好的方法来获得所需的输出 要复制的代码 CREATE TABLE Dummy_tab ( empid in

我有一个表,它有两个日期列,并以下面的方式比较日期,这样date1应该小于date2,但date1应该是其组中的最新日期

我可以得到我想要的结果,但问题是,这可能不是最好的方法,因为在我的原始表中,我有数百万条记录和大约30-40列

因此,在编写select时,我将使用max(col1)、max(col2)、…max(col40),这将非常繁琐,而且不是正确的方法,我想知道是否有更好的方法来获得所需的输出

要复制的代码

CREATE TABLE Dummy_tab (
    empid int,
    date1_start date,
    date2_start date,
    name_emp varchar(255)
);
 

INSERT INTO Dummy_tab VALUES
  (1, '2018-02-27','2018-02-28', 'Eric'),
  (1, '2016-02-28','2018-02-28', 'Eric'),
  (1, '2018-01-28','2018-02-28', 'Eric'),
  (2, '2018-10-28','2018-12-28', 'Jack'),
  (2, '2018-02-28','2018-12-28', 'Jack'),
  (2, '2018-11-28','2018-12-28', 'Jack'),
  (2, '2018-12-20','2018-12-28', 'Jack'),
  (2, '2018-12-28','2018-12-28', 'Jack'),
  (3, '2018-12-28','2018-12-31', 'Jane'),
  (3, '2018-12-28','2018-12-31', 'Jane');

  select empid,
         max(date1_start),
         max(date2_start),
         max(name_emp)
  from Dummy_tab
  where date2_start > date1_start
  group by empid


此查询返回预期的输出

with rn_cte as (
    select *, row_number() over (partition by empid order by date1_start desc) rn
    from Dummy_tab
    where date2_start > date1_start)
select * 
from rn_cte rc
where rn=1;
输出

empid   date1_start date2_start name_emp    rn
1       2018-02-27  2018-02-28  Eric        1
2       2018-12-20  2018-12-28  Jack        1
3       2018-12-28  2018-12-31  Jane        1
在澄清所有数据都在一行之后进行编辑-只想找到每个人的最新一行

为了得到正确的结果(例如,查找每个人的“最近一行”,但date1早于date2),请使用@SteveC的答案。它提供了您想要的内容,虽然它进行了完整的索引扫描,但它通常会有良好的性能(我已经对它进行了升级)。如果您只想偶尔运行此操作,或者您愿意等待多长时间(例如,10秒),那么这就是您的答案,您不需要再做更多的操作

但是,如果需要花费太长时间,您可能需要在此进一步考虑如何优化从表中读取数据的注意事项。这可能会加快处理速度,尤其是当每个人都有很多行时。另一方面,如果每个员工只有几行,这些可能没有什么区别

(注意,根据OP对评论的回答,我还清理了一些不相关的东西)


如果需要date1\u start小于date2\u start,则始终需要执行完整的表或索引扫描:它将无法查找索引中的特定点,因为它需要计算每行的差异

然后,通过排序/分组来烧掉CPU。在大多数查询中,排序(和groupby,这需要排序)往往是占用最多CPU时间的事情

你可以试试

  • 将分组依据修改为按更多字段分组,而不是使用MAX
  • 使用CTE和/或窗口功能
但是,您仍然会遇到相同的问题:它仍然需要执行完整的索引扫描和排序

如果查询速度不够快,其中一个问题可能与读取的数据量有关。如果你能减少,它可能会更快

首先,如果每个员工有许多行(并且您的表有一个主键,不是堆),那么您可以执行一个过程,首先为相关行标识PK,然后将其连接到原始表以获取该行的所有值。在这种情况下,您可以执行MAX(date1_start)而不是ROW_NUMBER(),因此不需要执行完全排序。但是,它需要再次查找聚集索引。通过索引(例如,emp_id、date1和date2上的索引)减少读取,可以加快速度

如果您可以更改表,并且非常需要经常运行该表,那么您可以添加一个(例如,当date2_start>date1_start然后是DATEDIFF(day,date2_start,date1_start)或者NULL END)的CASE,然后在其上放置一个索引和empid,这意味着您可以使用这些索引和empid进行计算(例如,按员工查找最大日期差)


但是,如果您必须执行过多的索引查找/键查找,它可能会决定执行聚集索引扫描(这取决于每个人有多少行-如果每个人都有很多行,这可能真的很有帮助。如果每个人只有几行,则可能没有).

只需检查-附加的30-40列-对于给定员工,它们在所有行中是相同的,还是不同的?类似地,对于给定的员工(比如Eric),其他30-40列的值是否全部取自一行,或者是否可以取自不同的行(例如,您是否只对最后一行感兴趣,或者基于该人员的所有行进行计算)?@DaleK所有员工的列都相同,eric和其他人的“是”值取自一行,但日期2应更大,日期1应为eric所有条目中的最新日期