如何基于Datetime列按1小时间隔获取一年的SQL数据?
解决按1小时间隔获取年度数据的SQL问题
首先,你的原SQL语句存在两个核心问题:
GROUP BY HOUR(DateTime)会把所有日期中同一小时的数据(比如2017-03-01 09点、2017-03-02 09点...)合并成一组,而不是你需要的「每天每小时」的间隔分组;- SELECT子句中的
ColumnT、ColumnV等列既不在GROUP BY中,也没有使用聚合函数,这会触发SQL的分组规则错误(部分宽松模式的数据库可能返回不可预料的结果)。
下面根据不同的需求场景,给出对应的可行方案:
场景1:每小时取一条数据(最新/最早)
如果你需要每个小时区间内的第一条或最新一条数据,可以用窗口函数ROW_NUMBER()来实现:
WITH HourlyData AS ( SELECT datetime, ColumnT, ColumnV, ColumnVV, -- 按「日期+小时」分组,每组内按datetime排序(DESC取最新,ASC取最早) ROW_NUMBER() OVER (PARTITION BY CAST(datetime AS DATE), DATEPART(HOUR, datetime) ORDER BY datetime DESC) AS rn FROM [Server].[dbo].[Table] WHERE ColumnT LIKE 'XXXX' AND DateTime BETWEEN '2017-03-01 09:00:00' AND '2018-03-01 09:00:00' ) SELECT datetime, ColumnT, ColumnV, ColumnVV FROM HourlyData WHERE rn = 1; -- 筛选出每组的第一条数据
场景2:每小时的聚合统计数据
如果需要对每小时的数据做聚合计算(比如平均值、总和、最大值等),可以对非分组列使用聚合函数:
SELECT -- 生成每小时的起始时间作为分组标识 DATEADD(HOUR, DATEPART(HOUR, datetime), CAST(CAST(datetime AS DATE) AS DATETIME)) AS HourStart, ColumnT, -- 因为WHERE中限定了ColumnT LIKE 'XXXX',所以可以直接包含在GROUP BY中 AVG(ColumnV) AS Avg_ColumnV, -- 示例:计算ColumnV的小时平均值 MAX(ColumnVV) AS Max_ColumnVV -- 示例:计算ColumnVV的小时最大值 FROM [Server].[dbo].[Table] WHERE ColumnT LIKE 'XXXX' AND DateTime BETWEEN '2017-03-01 09:00:00' AND '2018-03-01 09:00:00' GROUP BY CAST(datetime AS DATE), DATEPART(HOUR, datetime), ColumnT ORDER BY HourStart;
场景3:生成连续的小时序列(无数据也显示)
如果需要确保每一个小时区间都出现在结果中(即使该小时没有数据),可以先生成连续的小时序列,再左连接原表数据:
-- 生成从起始到结束的所有小时点 WITH HourlySequence AS ( SELECT CAST('2017-03-01 09:00:00' AS DATETIME) AS HourStart UNION ALL SELECT DATEADD(HOUR, 1, HourStart) FROM HourlySequence WHERE HourStart < '2018-03-01 09:00:00' ), -- 处理原表的小时数据,筛选出每小时最新的一条 TableHourly AS ( SELECT DATEADD(HOUR, DATEPART(HOUR, datetime), CAST(CAST(datetime AS DATE) AS DATETIME)) AS HourStart, ColumnT, ColumnV, ColumnVV, ROW_NUMBER() OVER (PARTITION BY CAST(datetime AS DATE), DATEPART(HOUR, datetime) ORDER BY datetime DESC) AS rn FROM [Server].[dbo].[Table] WHERE ColumnT LIKE 'XXXX' AND DateTime BETWEEN '2017-03-01 09:00:00' AND '2018-03-01 09:00:00' ) SELECT hs.HourStart, th.ColumnT, th.ColumnV, th.ColumnVV FROM HourlySequence hs LEFT JOIN TableHourly th ON hs.HourStart = th.HourStart AND th.rn = 1 ORDER BY hs.HourStart;
内容的提问来源于stack exchange,提问作者bowbow
相关产品推荐
相关产品推荐

