【问题标题】:Aggregate at 10 minutes for last 24 hours in dbdb 中过去 24 小时的 10 分钟聚合
【发布时间】:2020-09-14 12:36:26
【问题描述】:

以下查询将给定的时间范围数据拆分为 5 分钟,但它从提供的时间范围开始执行此操作

With MNE
AS
(
SELECT *,DATEDIFF(dd,0,t.datetime) AS dayoffset,
DATEDIFF(ss,MIN(t.datetime) OVER (PARTITION BY DATEDIFF(dd,0,t.datetime)),t.datetime)/60 AS MinOffset
FROM cw.datas t
 WHERE t.DATETIME <= GETDATE()
 AND t.DATETIME > DATEADD(SECOND, -DATEDIFF(SECOND, CAST(CAST(GETDATE() AS DATE) AS DATETIME),
 GETDATE()) % (60 * 5), DATEADD(DAY, - 1,GETDATE()))
)

SELECT  MIN(z.datetime) AS StartDatetime,
 MAX(z.datetime) AS ENdDatetime,
 sum(z.value) AS TotalSum
FROM MNE z
GROUP BY dayoffset,(MinOffset-1)/10
order by StartDatetime

当前时间为2020-09-14 12:28:43.793,输出如下:

StartDatetime,ENdDatetime,TotalSum
2020-09-13 12:25:03.000,    2020-09-13 12:31:00.000,    63763.51
2020-09-13 12:31:03.000,    2020-09-13 12:36:00.000,    48348.34
2020-09-13 12:36:03.000,    2020-09-13 12:41:00.000,    54387.69
--
--
2020-09-14 12:16:00.000,    2020-09-14 12:20:57.000,    54353.72
2020-09-14 12:21:00.000,    2020-09-14 12:25:57.000,    53780.48
2020-09-14 12:26:00.000,    2020-09-14 12:28:42.000,    25328.56

我想从当前时间戳(即2020-09-14 12:28:43.793)聚合拆分到过去 24 小时。

Expected result :

StartDatetime,ENdDatetime,TotalSum
--
--
2020-09-14 11:58:43.000,    2020-09-14 12:08:43.000,    354654
2020-09-14 12:08:43.000,    2020-09-14 12:18:43.000,    354353
2020-09-14 12:18:43.000,    2020-09-14 12:28:43.000,    354665


帮助表示赞赏。

样本数据:

datas

datetime,   abc,    def,    ghi,    value
2020-09-11 12:22:36.000,    AYSH,   mains,  SAE,    363.12
2020-09-11 12:22:39.000,    AYSH,   mains,  SAE,    358.2
2020-09-11 12:22:42.000,    AYSH,   mains,  SAE,    353.66
2020-09-11 12:22:45.000,    AYSH,   mains,  SAE,    349.14
2020-09-11 12:22:48.000,    AYSH,   mains,  SAE,    344.84
2020-09-11 12:22:51.000,    AYSH,   mains,  SAE,    340.63
2020-09-11 12:22:54.000,    AYSH,   mains,  SAE,    336.45

【问题讨论】:

  • 可以添加示例数据和预期结果吗?
  • @Vernou 给出了样本数据

标签: sql-server datetime


【解决方案1】:

您没有为cw.datas 提供表定义,因此我无法将我的解决方案应用于您的查询。

此递归 CTE 生成 144 个间隔,持续时间为 10 分钟,从现在开始,回溯到 24 小时。

with stamps as
(
  select getdate() as Stamp, 0 as Interval
    union all
  select dateadd(MI, -10, s.Stamp), s.Interval+1
  from stamps s
  where s.Interval < 144 -- 24 hours * 6 10-minute intervals = 144 10-minute intervals
)
select s.Stamp as FromDateTime,
       dateadd(MI, 10, s.Stamp) as ToDateTime,
       s.Interval
from stamps s
order by s.Stamp
option(maxrecursion 144);

输出如下:

FromDateTime                ToDateTime                  Interval
--------------------------- --------------------------- ---------
2020-09-13 14:00:54.740     2020-09-13 14:10:54.740     144
2020-09-13 14:10:54.740     2020-09-13 14:20:54.740     143
2020-09-13 14:20:54.740     2020-09-13 14:30:54.740     142
2020-09-13 14:30:54.740     2020-09-13 14:40:54.740     141
2020-09-13 14:40:54.740     2020-09-13 14:50:54.740     140
... 
2020-09-14 13:10:54.740     2020-09-14 13:20:54.740     5
2020-09-14 13:20:54.740     2020-09-14 13:30:54.740     4
2020-09-14 13:30:54.740     2020-09-14 13:40:54.740     3
2020-09-14 13:40:54.740     2020-09-14 13:50:54.740     2
2020-09-14 13:50:54.740     2020-09-14 14:00:54.740     1
2020-09-14 14:00:54.740     2020-09-14 14:10:54.740     0

Fiddle 1


结合给定的样本数据。

样本数据

create table data
(
  stamp datetime,
  abc nvarchar(4),
  def nvarchar(5),
  ghi nvarchar(3),
  value decimal(10,2)
);

insert into data (stamp, abc, def, ghi, value) values
('2020-09-11 12:22:36.000', 'AYSH', 'mains', 'SAE', 363.12),
('2020-09-11 12:22:39.000', 'AYSH', 'mains', 'SAE', 358.2 ),
('2020-09-11 12:22:42.000', 'AYSH', 'mains', 'SAE', 353.66),
('2020-09-11 12:22:45.000', 'AYSH', 'mains', 'SAE', 349.14),
('2020-09-11 12:22:48.000', 'AYSH', 'mains', 'SAE', 344.84),
('2020-09-11 12:22:51.000', 'AYSH', 'mains', 'SAE', 340.63),
('2020-09-11 12:22:54.000', 'AYSH', 'mains', 'SAE', 336.45);

解决方案

定义参考日期时间,因为getdate() 使用2020-09-11 的样本数据生成的结果很少。

declare @refStamp datetime = '2020-09-12 00:00:00.000'; -- replacement for getdate()

with stamps as
(
  select @refStamp as FromDateTime,
         dateadd(MI,10,@refStamp) as ToDateTime,
         0 as Interval
    union all
  select dateadd(MI, -10, s.FromDateTime),
         s.FromDateTime,
         s.Interval+1
  from stamps s
  where s.Interval < 144 -- 24 hours * 6 10-minute intervals = 144 10-minute intervals
)
select s.FromDateTime,
       s.ToDateTime,
       d.abc,
       sum(d.value) as SumValues
from stamps s
left join data d
  on  d.stamp >= s.FromDateTime              -- greater than or equal to FromDateTime
  and d.stamp <  s.ToDateTime                -- smaller than ToDateTime
where s.FromDateTime >= '2020-09-11 12:00:00.000'   -- limit output results (part 1)
  and s.FromDateTime <= '2020-09-11 13:00:00.000'   -- limit output results (part 2)
group by s.FromDateTime, s.ToDateTime, d.abc
order by s.FromDateTime
option(maxrecursion 144);

结果

FromDateTime             ToDateTime               abc   SumValues
------------------------ ------------------------ ----- ----------
2020-09-11 12:00:00.000  2020-09-11 12:10:00.000  NULL  NULL
2020-09-11 12:10:00.000  2020-09-11 12:20:00.000  NULL  NULL
2020-09-11 12:20:00.000  2020-09-11 12:30:00.000  AYSH  2446.04
2020-09-11 12:30:00.000  2020-09-11 12:40:00.000  NULL  NULL
2020-09-11 12:40:00.000  2020-09-11 12:50:00.000  NULL  NULL
2020-09-11 12:50:00.000  2020-09-11 13:00:00.000  NULL  NULL
2020-09-11 13:00:00.000  2020-09-11 13:10:00.000  NULL  NULL

Fiddle 2

【讨论】:

  • 感谢上述小提琴,您已经正确生成了间隔。我希望在现有表中的这些间隔中进行聚合,这些间隔中有秒间隔的数据。考虑上面的示例
  • @Arshanvit,解决方案扩展为对样本数据执行聚合。
【解决方案2】:

如果数据很密集,那么实际上没有必要使用递归查询。只需计算自startTime 以来经过的秒数。而且这个表格可以让你轻松调整区间的范围开始和大小。

with timeRelatedFields as (
    select
        dateadd(hour, -24,
            dateadd(millisecond, -datepart(millisecond, getdate()), 
                getdate())) as startTime,
        600 as intervalSeconds
), tableTimeRelatedFields as (   
    select *,
        d.value as consideredValue,
        datediff(second, st.startTime, d."datetime") / intervalSeconds as interval
    from cw.datas as d cross apply timeRelatedFields as st
    where d."datetime" >= startTime and d."datetime" < getdate()
)
select
    dateadd(second, intervalSeconds *  interval,      startTime) as StartDateTime,
    dateadd(second, intervalSeconds * (interval + 1), startTime) as EndDateTime,
    sum(consideredValue) as TotalSum      
from tableTimeRelatedFields
group by interval;

【讨论】:

  • 请将其限制为当前时间戳,因为当前它将是一天中的最后一个时间戳,实际问题是仅在过去 24 小时内获取当前时间戳。还有dateadd(second, intervalSeconds * interval, startTime) as StartDateTime, dateadd(second, intervalSeconds * (interval + 1), startTime) as EndDateTime,以下字段intervalSecondsstartTime 无法访问。
猜你喜欢
  • 1970-01-01
  • 2017-03-16
  • 2023-04-07
  • 2017-02-13
  • 2020-01-08
  • 1970-01-01
  • 1970-01-01
  • 2017-11-12
  • 1970-01-01
相关资源
最近更新 更多