基于日期范围的 SQL 查询

SQL query based on date range

提问人:hendra sps 提问时间:9/21/2023 最后编辑:Dale Khendra sps 更新时间:9/21/2023 访问量:58

问:

我有桌子

emp_id date_time
E001系列 23-01-01 07:08
E001系列 23-01-01 16:07
E001系列 23-01-03 07:45
E001系列 23-01-03 16:01

我想查询以显示基于日期范围的结果。例如,我将 e001 的日期范围从 23-01-01 设置为 23-01-03,则结果为:

日期
23-01-01 07:08 16:07
23-01-02
23-01-03 07:45 16:01
sql-server 联接 日期范围

评论

1赞 Thom A 9/21/2023
看起来像一个日历表和/是你想要的。你试过什么?为什么它不起作用?MINMAX
1赞 Thom A 9/21/2023
此外,这些日期非常模棱两可。那是 2023 年 1 月 1 日吗?1923?1901年1月23日?2001 年 23 月 1 日?
0赞 hendra sps 9/21/2023
是的,这是一个出勤表,我试过了:选择 emp_id,MIN(date_time) 为 [IN],MAX(date_time) 为 [OUT] 其中date_time在“2023-01-01 00:00:00.000”和“2023-01-03 23:59:59.999”之间,但结果不是显示日期 2023-01-02,因为没有条目。我想要的是结果显示日期 2023-01-02 在没有条目时为 null
0赞 Thom A 9/21/2023
这就是为什么,正如我所提到的,你需要一个日历表。

答:

0赞 Patrick Hurst 9/21/2023 #1

以您的示例数据为例,并将其转换为一些 DDL/DML(这是您在提出这些类型的问题时应该做的非常有用的第一步):

DECLARE @Table TABLE (emp_id VARCHAR(4), date_time DATETIME);
INSERT INTO @Table (emp_id, date_time) VALUES
('e001', '2023-01-01 07:08'),
('e001', '2023-01-01 16:07'),
('e001', '2023-01-03 07:45'),
('e001', '2023-01-03 16:01');

这成为数据外推的简单练习,以确保每个间隔都有行。我们可以简单地使用 .然后,从完整数据集联接回表的聚合(假设您只希望第一个日期时间作为 IN,最后一个日期时间作为 OUT,它们不匹配)。CTE

最后,只需应用谓词来限制日期范围:

;WITH Dates AS (
SELECT MIN(CAST(date_time AS DATE)) AS mnDate, MAX(CAST(date_time AS DATE)) AS mxDate FROM @Table
UNION ALL
SELECT DATEADD(DAY,1,mnDate), mxDate
  FROM Dates
 WHERE mnDate < mxDate
)

SELECT mnDate AS Date, InDateTime, OutDateTime
  FROM Dates d
    LEFT OUTER JOIN (
                     SELECT CAST(date_time AS DATE) AS date, MIN(date_time) AS InDateTime, NULLIF(MAX(date_time),MIN(date_time)) AS OutDateTime 
                       FROM @Table 
                      GROUP BY CAST(date_time AS DATE)
                    ) a
      ON d.mnDate = a.date
 WHERE d.mnDate BETWEEN '2023-01-01' AND '2023-01-03';
日期 InDateTime(日期时间) OutDateTime(OutDateTime)
2023-01-01 2023-01-01 07:08:00.000 2023-01-01 16:07:00.000
2023-01-02
2023-01-03 2023-01-03 07:45:00.000 2023-01-03 16:01:00.000

评论

0赞 Thom A 9/21/2023
希望 OP 正在处理较小的日期范围。如果没有,则理货或预先存在的日历表将是 rCTE 的性能更高的解决方案
2赞 Patrick Hurst 9/21/2023
跨越两年的 rCTE 将少于 800 行,即使在我笨拙的笔记本电脑上也能执行亚秒级。当然,如果将数据集扩展到企业规模,则需要考虑调优和性能选项,但我认为这可能超出了问题的范围。