sql - 按小时分组计数(从-到)

标签 sql sql-server group-by

我在查询时遇到问题,必须计算行数并返回数字作为结果。关键是我需要最近 24 小时的数据除以一小时的时间段。我已经使用 UNION ALL 完成了这个查询 24 次,但是 SQL 单个查询有 800 多行(令人惊讶的是只需要 3 秒)。我知道我可以以某种方式按时间分组,但不知道如何正确执行。我坚信相等查询只需大约 20-30 行 SQL。我将不胜感激任何线索。这里您有我提到的一些简化查询。

长查询(使用 UNION ALL):

DECLARE @CurrentTime datetime = GETDATE();

--Data from 1 hour
SELECT
----Time
(SELECT CONVERT(VARCHAR(5), (DATEADD(HOUR, -1, @CurrentTime)), 114)) AS [Time],

----Count on 1st table
(SELECT COUNT(T1.[TableFirstId])
FROM [dbo].[Table1] AS T1
WHERE T1.[IncomingDate] BETWEEN (DATEADD(HOUR, -1, @CurrentTime)) AND @CurrentTime) AS [CountT1],
----Count on 2nd table
(SELECT COUNT(T2.[TableSecondId])
FROM [dbo].[Table2] AS T2
WHERE T2.[IncomingDate] BETWEEN (DATEADD(HOUR, -1, @CurrentTime)) AND @CurrentTime) AS [CountT2],
----Count on 3rd table
(SELECT COUNT(T3.[TableThirdId])
FROM [dbo].[Table3] AS T3
WHERE T3.[IncomingDate] BETWEEN (DATEADD(HOUR, -1, @CurrentTime)) AND @CurrentTime) AS [CountT3]

UNION ALL

--Data from 2 hours
SELECT
----Time
(SELECT CONVERT(VARCHAR(5), (DATEADD(HOUR, -2, @CurrentTime)), 114)) AS [Time],

----Count on 1st table
(SELECT COUNT(T1.[TableFirstId])
FROM [dbo].[Table1] AS T1
WHERE T1.[IncomingDate] BETWEEN (DATEADD(HOUR, -2, @CurrentTime)) AND (DATEADD(HOUR, -1, @CurrentTime))) AS [CountT1],
----Count on 2nd table
(SELECT COUNT(T2.[TableSecondId])
FROM [dbo].[Table2] AS T2
WHERE T2.[IncomingDate] BETWEEN (DATEADD(HOUR, -2, @CurrentTime)) AND (DATEADD(HOUR, -1, @CurrentTime))) AS [CountT2],
----Count on 3rd table
(SELECT COUNT(T3.[TableThirdId])
FROM [dbo].[Table3] AS T3
WHERE T3.[IncomingDate] BETWEEN (DATEADD(HOUR, -2, @CurrentTime)) AND (DATEADD(HOUR, -1, @CurrentTime))) AS [CountT3]

UNION ALL

--Data from 3 hours
SELECT
----Time
(SELECT CONVERT(VARCHAR(5), (DATEADD(HOUR, -3, @CurrentTime)), 114)) AS [Time],

----Count on 1st table
(SELECT COUNT(T1.[TableFirstId])
FROM [dbo].[Table1] AS T1
WHERE T1.[IncomingDate] BETWEEN (DATEADD(HOUR, -3, @CurrentTime)) AND (DATEADD(HOUR, -2, @CurrentTime))) AS [CountT1],
----Count on 2nd table
(SELECT COUNT(T2.[TableSecondId])
FROM [dbo].[Table2] AS T2
WHERE T2.[IncomingDate] BETWEEN (DATEADD(HOUR, -3, @CurrentTime)) AND (DATEADD(HOUR, -2, @CurrentTime))) AS [CountT2],
----Count on 3rd table
(SELECT COUNT(T3.[TableThirdId])
FROM [dbo].[Table3] AS T3
WHERE T3.[IncomingDate] BETWEEN (DATEADD(HOUR, -3, @CurrentTime)) AND (DATEADD(HOUR, -2, @CurrentTime))) AS [CountT3]

UNION ALL

--(etc...)

这个查询给了我类似的东西:

Time    |   CountT1   |   CountT2   |   CountT3

21:05   |   3215467   |   3456364   |   3234234

20:05   |   2253221   |   3123123   |   3238291

19:05   |   1231467   |    1232342  |   1123123

18:05   |   3112412   |    6712353  |   1233124

17:05   |   1242141   |   1241142   |   4112426

16:05   |   3123467   |   3456364   |   3234234

15:05   |   3215467   |   3412334   |   3231234

14:05   |   3324467   |   3456123   |   2312334

13:05   |   3215467   |   3456364   |   1112310

12:05   |   3215467   |   3456364   |   1231234

11:05   |   3123127   |   3456364   |   3234234

10:05   |   3215467   |   3456364   |   3234234

09:05   |   3215467   |   3456364   |   3234234

08:05   |   3215467   |   3456364   |   3234234

07:05   |   3215467   |   3456364   |   3234234

06:05   |   3215467   |   3456364   |   3234234

05:05   |   3215467   |   2212214   |   3234234

04:05   |   3215467   |   3126542   |   3234234

03:05   |   3215467   |   3123364   |   3234234

02:05   |   3215467   |   3456364   |   3234234

01:05   |   3215467   |   3456364   |   3234234

00:05   |   3215467   |   3456364   |   3123123

23:05   |   3215467   |   3456364   |   3212313

22:05   |   3223424   |   1232163   |   1235321

我需要通过更简单的查询返回相同的结果(考虑这样的事情):

DECLARE @CurrentTime datetime = GETDATE();

--Data from 24 hours
SELECT

----Count on 1st table
(SELECT COUNT(T1.[TableFirstId])
FROM [dbo].[Table1] AS T1
WHERE T1.[IncomingDate] BETWEEN (DATEADD(HOUR, -24, @CurrentTime)) AND @CurrentTime) AS [CountT1],
----Count on 2nd table
(SELECT COUNT(T2.[TableSecondId])
FROM [dbo].[Table2] AS T2
WHERE T2.[IncomingDate] BETWEEN (DATEADD(HOUR, -24, @CurrentTime)) AND @CurrentTime) AS [CountT2],
----Count on 3rd table
(SELECT COUNT(T3.[TableThirdId])
FROM [dbo].[Table3] AS T3
WHERE T3.[IncomingDate] BETWEEN (DATEADD(HOUR, -24, @CurrentTime)) AND @CurrentTime) AS [CountT3]

FROM [dbo].[Table1] AS T1
GROUP BY DATEPART(HOUR, T1.[IncomingDate])

但是它并没有按照我的预期工作。有谁能帮助我理解这一点吗?并解决我的问题?

最佳答案

此查询将为您提供与使用较少 SQL 的查询完全相同的结果。

DECLARE @HourTbl TABLE ( HourBegin DATETIME, HourEnd DATETIME)
DECLARE @i INT=0
DECLARE @dtBegin datetime 
DECLARE @dtEnd datetime = GETDATE()

WHILE @i < 24
BEGIN
    SET @i = (@i + 1)
    SET @dtBegin = @dtEnd
    SET @dtEnd = DATEADD(HOUR, -@i, @dtBegin)
    INSERT  INTO @HourTbl
    SELECT   @dtBegin, @dtEnd   
END

;with hourVal (  hourBegin , hourEnd )
as
(

select  hourBegin, hourend
from @HourTbl
)
select CONVERT(VARCHAR(5), hourVal.hourBegin, 114), 
(
select  COUNT(T1.[TableFirstId]) 
from Table1
where T1.[IncomingDate] BETWEEN hourVal.hourBegin, hourVal.hourEnd
),
(
select COUNT(T1.[TableFirstId]) 
from Table2
where T1.[IncomingDate] BETWEEN hourVal.hourBegin, hourVal.hourEnd
)

关于sql - 按小时分组计数(从-到),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25796048/

相关文章:

sql - Postgres : Combine update queries to one query on hierarchic table

sql - 如何使用 Oracle 声明带有 OR 条件的外键?

mysql - 提高sql查询性能

sql - 如何在Sql中为临时表设置order by

sql-server - SQL Server性能: GROUP BY int vs GROUP BY VARCHAR

sql - 如果存在还是存在?

sql - 如何在 SQL Server 上对提交进行分页

带有二进制的 SQL WHERE 子句

mysql - MySQL 中的条件行排名

oracle - 从 Rollup 获取所需的输出