如何编写SQL获取1个月内每日固定时段的人员交易记录
1个月时段数据查询实现方案
查询配置参考界面:
原有循环写法的问题
你写的WHILE循环无法返回预期结果,核心问题如下:
- 循环内的SELECT语句没有将查询结果写入临时表或表变量,数据库不会自动合并多轮循环的查询结果,最终要么抛出语法错误,要么仅返回最后一轮循环查到的单条数据
- 日期偏移计算逻辑错误:初始变量@i=0,第一轮循环时@i+1=1,查询起始时间直接跳到2022-06-02 07:00,漏掉了基准日2022-06-01当天的有效数据
- 硬编码循环31天没有适配自然月天数规则,遇到30天的小月、2月时会查出跨月的无效数据
- 逐天循环属于逐行操作,查询性能很差,这类时间范围过滤场景完全可以用集合式SQL一次性实现,不需要编写循环逻辑。
正确查询写法
不需要使用WHILE循环,直接通过整体时间范围+每日时段过滤即可完成查询,小时、分钟级精度不会有损失。
返回时段内所有符合条件的记录
SELECT Tarih FROM PersonelTransaction WHERE PersonelId = 175 AND CompanyId = 1 -- 限定整体查询范围:从基准时间开始往后1个月 AND Tarih >= '20220601 07:00' AND Tarih < DATEADD(MONTH, 1, '20220601 07:00') -- 限定每日有效时段:07:00-18:50,直接提取时间部分判断,精度到分钟 AND CAST(Tarih AS TIME) BETWEEN '07:00' AND '18:50' AND Aktif IN ('0', '2') AND TerminalId NOT IN (9, 10, 11, 12) AND Yon = 2
对齐原Top 1逻辑(每日仅返回1条匹配记录)
如果你原语句里的Top 1是需要每天只返回1条匹配记录(比如取当天最早的匹配记录),可以直接通过分组实现,不需要循环:
SELECT CONVERT(DATE, Tarih) AS query_date, MIN(Tarih) AS match_tarih -- 取当天最早记录,如需取最晚记录替换为MAX即可 FROM PersonelTransaction WHERE PersonelId = 175 AND CompanyId = 1 AND Tarih >= '20220601 07:00' AND Tarih < DATEADD(MONTH, 1, '20220601 07:00') AND CAST(Tarih AS TIME) BETWEEN '07:00' AND '18:50' AND Aktif IN ('0', '2') AND TerminalId NOT IN (9, 10, 11, 12) AND Yon = 2 GROUP BY CONVERT(DATE, Tarih)
关键说明
- 用
CAST(Tarih AS TIME)提取字段的时间部分做时段判断,不会丢失小时、分钟级精度,完全满足你的精度要求 - 用
DATEADD(MONTH,1,基准时间)自动计算1个月后的截止时间,不需要手动判断当月天数,不会出现多查、漏查的问题 - 集合式查询的性能远高于逐天循环写法,数据量越大性能优势越明显。
内容的提问来源于stack exchange,提问作者Süleyman Sülün
相关产品推荐
相关产品推荐

