不同日期/时间之间的总和天数

时间:2016-12-21 13:41:22

标签: sql-server stored-procedures

通过对一天的值求和,我的查询完全正常。

SELECT CAST(fldDateTime AS DATE) AS DayValue, SUM(fldValue) AS Val
FROM [dbo].[Data.tblMeterData]
GROUP BY CAST(fldDateTime AS DATE)
ORDER BY DayValue 

我遇到的问题是我需要将数据大于午夜并持续到第二天的午夜。为了测试我可以做到这一点,我测试了以下代码,这有助于我处理没有一整天的第一批值。

 DECLARE @a DATETIME
 DECLARE @b DATETIME

SET @a = CAST('2016-03-21 00:01:00' AS DATETIME)
SET @b = DATEADD(SECOND,-86399 ,@a)
SELECT @a AS a, @b AS b

SELECT CAST(fldDateTime AS DATE) AS DayValue, SUM(fldValue) AS Val
FROM [dbo].[Data.tblMeterData]
WHERE fldDateTime BETWEEN @b AND @a
GROUP BY CAST(fldDateTime AS DATE)
ORDER BY DayValue 

这个问题是我不想循环浏览日期,因为我有成千上万的ID需要以这种方式处理。我不能包括第一个日期的午夜,因为第一个数据是在午夜之后录制,最后的每日阅读时间是第二天的午夜,例如

    Date > '2016-03-20 00:00:00' AND <= 2016-03-21 00:00:00

如何执行以下操作:

  • 查找ID的第一个日期,然后升级到第二天的第一个午夜,并在接下来的几天内重复此操作。
  • 将这些值相加,使它们大于午夜并且直到第二天的午夜。

2 个答案:

答案 0 :(得分:1)

我对要求的理解是,您正在寻找按度计ID和日期计算的值组的总和,但是对于每个日期,我们还希望包含第二天的值。这意味着每个值将计入当天和前一天的总和。

代码:

--generate test data
declare @tblMeterData table (
        [ID] [int] IDENTITY(1,1) NOT NULL,
        [tblMeterData_Id] [int] NOT NULL,
        [fldDateTime] [datetime] NOT NULL,
        [fldValue] [decimal](18, 2) NULL,
        [fldBatchId] [uniqueidentifier] NOT NULL);

insert  @tblMeterData (tblMeterData_Id, fldDateTime, fldValue, fldBatchId) values
        (18, '2016-12-19 23:59:59', 1.0, newid()),
        (18, '2016-12-20 00:00:00', 2.0, newid()),
        (18, '2016-12-20 00:30:00', 3.0, newid()),
        (18, '2016-12-20 01:00:00', 4.0, newid()),
        (18, '2016-12-20 01:30:00', 5.0, newid()),
        (18, '2016-12-21 00:00:00', 6.0, newid()),
        (18, '2016-12-21 00:30:00', 7.0, newid()),
        (18, '2016-12-22 00:00:00', 8.0, newid()),
        (18, '2016-12-23 00:00:00', 9.0, newid()),
        (19, '2016-12-20 00:00:00', 10.0, newid());

--select    * from @tblMeterData order by ID;

--main query
with cte as (
        --0:00:00 reports on previous day
        select  *, cast(dateadd(S, -1, fldDateTime) as date) group_date
        from    @tblMeterData

        union   all

        --duplicate all records to also group on previous day
        select  *, cast(dateadd(D, -1, dateadd(S, -1, fldDateTime)) as date) group_date
        from    @tblMeterData
)
select  tblMeterData_Id, group_date, sum(fldValue) sum_value
from    cte
group   by tblMeterData_Id, group_date
order   by tblMeterData_Id, group_date;

结果:

tblMeterData_Id group_date  sum_value
18      2016-12-18  3.00
18      2016-12-19  21.00
18      2016-12-20  33.00
18      2016-12-21  24.00
18      2016-12-22  9.00
19      2016-12-18  10.00
19      2016-12-19  10.00

答案 1 :(得分:1)

答案如下:

WITH cte AS (       

SELECT *, CAST(DATEADD(S, -1, fldDateTime) AS DATE) group_date
FROM [dbo].[Data.tblMeterData]              

)
SELECT  tblMeterData_Id, group_date, SUM(fldValue) sum_value
FROM    cte
GROUP   BY tblMeterData_Id, group_date
ORDER   BY tblMeterData_Id, group_date;

效果很好。