我有一台设备以随机时间间隔报告其生产件数。在每条记录中,内部计数器被重置,所以如果我想获得总数,我会在一段时间内总结。
ts pieces
--------------------------------
2013-01-23 11:58 2013
2013-01-23 12:12 3025
2013-01-23 12:12 3025
2013-01-23 12:13 112
2013-01-23 12:17 1122
2013-01-23 12:34 3112
2013-01-23 12:36 3025
如果我想查询此数据并且我希望生成的作品从12:00到12:30,该怎么办?我不能简单地做到以下几点:
SELECT SUM(pieces)
FROM table
WHERE ts BETWEEN '2013-01-23 12:00' and '2013-01-23 12:30'
通过这个查询,我会在开头有太多的碎片(截至12:12报道的3025件有些是在12:00之前的2分钟内制作的)我最后会有太少的碎片(在12:17到12:30之间产生的碎片仅在12:34报道。
SQL服务器中是否有内置功能可以在基于时间的系列上进行此类计算,还是需要我根据dateDiff在区间中的第一个/最后一个值和最后/第一个外部之间手动插值?
答案 0 :(得分:0)
您必须手动进行插值。我根据各种其他假设(即ts
代表“直到并包括此分钟产生的所有项目”或“此分钟之前生成的所有项目”)构建了一些代码来执行此操作:
declare @t table (ts datetime2 not null,pieces int not null)
insert into @t(ts,pieces) values
('2013-01-23T11:58:00',2013),
('2013-01-23T12:12:00',3025),
--('2013-01-23T12:12:00',3025), --Error, two identical counts at same time?
('2013-01-23T12:13:00',112 ),
('2013-01-23T12:17:00',1122),
('2013-01-23T12:34:00',3112),
('2013-01-23T12:36:00',3025)
declare @Start datetime2
declare @End datetime2
select @Start = '2013-01-23T12:00:00', @End = '2013-01-23T12:30:00'
;With Numbers as (
select distinct number
from master..spt_values
), RowsNumbered as (
select
ROW_NUMBER() OVER (ORDER BY ts) as rn,
*
from @t
), Paired as (
select
rn2.ts as prevTime,
rn1.ts as thisTime,
rn1.pieces as pieces
from
RowsNumbered rn1
inner join
RowsNumbered rn2
on
rn1.rn = rn2.rn + 1
), Minutes as (
select
DATEADD(minute,-number,thisTime) as Time,
(pieces * 1.0) / DATEDIFF(minute,prevTime,thisTime) as Pieces
from
Paired p
inner join
Numbers n
on
number < 60 and --Reasonable?
DATEADD(minute,-number,thisTime) > prevTime and
number >= 0
)
select SUM(pieces)
from Minutes
where Time >= @Start and Time < @End
我也将开始和结束时间视为具有包含性开始和独占结束的半开放时间间隔。这通常是处理日期时间等连续数据的更明智的方法。
希望你能看到我是如何构建每个CTE的,从单个时间戳和件数到每分钟,有一个概念,即在那一分钟产生了多少件。一旦我们达到这一点,我们可以在我们想要包含的分钟内SUM
。{/ p>