sql - SQL Server 聚合窗口的区别
问题描述
我想通过从开始时间创建 15 分钟的窗口来从 SQL Server 表中获取一些数据,并在这些窗口中找到某个列(值)的 MAX 和 MIN 之间的差异。
SQL 表存储每分钟捕获的一些遥测数据。
是否有任何 T-SQL 功能可用于在不运行循环(窗口聚合排序等)的情况下获得此类输出?
我可以使用循环来实现这一点,但这非常慢,因为它会从每个窗口中获取数据并将其添加到临时表中。下面是一段简化的代码片段:
WHILE(@startTime <@endTimeInput)
BEGIN
INSERT INTO #energyDataTable
SELECT MIN(timeStamp) as startTime, MAX(timeStamp) as endTime, ROUND(MAX (value) - MIN (value),2) as value
FROM PLANT1.DATA_TABLE as ts
WHERE ts.unixTimestamp>=@startTime and ts.unixTimestamp<= @endTime
GROUP BY ts.logicalId
--Increment startTime and endTime to goto next window
SET @startTime = @endTime;
SET @endTime = @startTime + 15 * 60000; --converting 15 mins to millisecs
END
时间戳 | 价值 | Unix时间 |
---|---|---|
2021-11-08 00:00:09.000 | 1527.6 | 1636329609000 |
2021-11-08 00:01:09.000 | 1528.1 | 1636329669000 |
2021-11-08 00:02:09.000 | 1528.6 | 1636329729000 |
…… | …… | …… |
2021-11-08 00:13:09.000 | 1534.5 | 1636330389000 |
2021-11-08 00:14:09.000 | 1535.3 | 1636330479000 |
2021-11-08 00:15:09.000 | 1535.5 | 1636330509000 |
2021-11-08 00:16:09.000 | 1536.0 | 1636330569000 |
2021-11-08 00:17:09.000 | 1528.6 | 1636330629000 |
…… | …… | …… |
2021-11-08 00:28:09.000 | 1542.5 | 1636331289000 |
2021-11-08 00:29:09.000 | 1543.3 | 1636331379000 |
需要转换为(我不一定需要 end_time: 添加以便更好地理解):
开始时间 | 时间结束 | 价值 |
---|---|---|
2021-11-08 00:00:09.000 | 2021-11-08 00:14:39.000 | 7.7 |
2021-11-08 00:15:09.000 | 2021-11-08 00:29:39.000 | 7.8 |
解决方案
更新
解决方案是从 15 分钟部分获取第一行和最后一行
可以这样做:
create table #t
(
ts datetime2
,val dec(9,2)
)
insert into #t
values
('2021-11-08 00:00:09.000', 1527.6)
,('2021-11-08 00:01:09.000', 1528.1)
,('2021-11-08 00:02:09.000', 1528.6)
,('2021-11-08 00:13:09.000', 1534.5)
,('2021-11-08 00:14:09.000', 1535.3)
,('2021-11-08 00:15:09.000', 1535.5)
,('2021-11-08 00:16:09.000', 1536.0)
,('2021-11-08 00:17:09.000', 1528.6)
,('2021-11-08 00:28:09.000', 1542.5)
,('2021-11-08 00:29:09.000', 1543.3)
;with
cte_partitions as
(
select *
from
(
select *
,row_number() over(partition by M15.[partition] order by T.ts) as row_asc_id -- first row
,row_number() over(partition by M15.[partition] order by T.ts desc) as row_desc_id -- last row
from #t T
outer apply
(
-- 15 minutes partitions = hours + minutes / 15
select format(ts, 'yyyyMMddHH') + cast(datepart(minute, ts) / 15 as char(1)) as [partition]
) M15
) T
where T.row_asc_id = 1
or T.row_desc_id = 1
)
select PF.ts
,PL.val - PF.val
from cte_partitions PF
inner join cte_partitions PL
on PF.[partition] = pl.[partition]
where PF.row_asc_id = 1
and PL.row_desc_id = 1
尽管它与您的示例完全一致,但只有当您每分钟都没有秒等时,它才会起作用。
请看一下
create table #t
(
ts datetime2
,val int
)
insert into #t
values
('2021-11-09T01:01:00.000Z', 100)
,('2021-11-09T01:02:00.000Z', 102)
,('2021-11-09T01:03:00.000Z', 103)
,('2021-11-09T01:04:00.000Z', 105)
,('2021-11-09T01:05:00.000Z', 107)
,('2021-11-09T01:06:00.000Z', 108)
,('2021-11-09T01:07:00.000Z', 120)
,('2021-11-09T01:08:00.000Z', 123)
,('2021-11-09T01:09:00.000Z', 128)
,('2021-11-09T01:10:00.000Z', 135)
select format(ts, 'hh:mm:ss') + ' - ' + format(next_ts, 'hh:mm:ss')
,cast(next_val - val as varchar(10)) + ' (' + cast(next_val as varchar(10)) + ' - ' + cast(val as varchar(10)) + ')'
from
(
select ts
,val
,lead(ts) over(order by ts) as next_ts
,lead(val) over(order by ts) as next_val
from
(
select *, (row_number() over(order by ts) - 1) % 4 as row_id
from #t
) SQ
where row_id = 0
) SQ
where next_ts is not null
推荐阅读
- python - PyInstaller 陷入无限循环(钩子)
- android-auto - 在 Android Auto 中剪辑视频以完全填满屏幕
- flume - 如果我删除本地文件,flume 会删除远程文件吗?
- flutter - 使用借记卡进行 Flutter 应用内购买
- google-apps-script - 如何使用 Google Adsense 页脚广告代码?
- python - For循环ValueError:一个Series的真值不明确
- javascript - 如何制作没有标题或描述的嵌入 Discord.js
- sql - 如何使用分隔符拆分字符串并获取第一个值
- statistics - 如何使用有符号的地面实况值和无符号的预测值计算 ROC AUC
- python - 为什么图像显示时会闪烁?