我需要每天利用 SQL 查询对数据进行分箱,以便我可以将其放入箱中以在 SSRS 中用于报告,即上午 12 点至凌晨 12 点。我的行的时间间隔一直延伸到凌晨 12 点,可能持续多天。我想将扩展一个或多个上午 12 点时间边界的行拆分为多行,以便我可以按天分组进行一些求和。例如,这里有 3 行:
StateName StartDT LastDT IntervalMin FullName
RUN_PARTS 2017-01-24 23:09:29.46 2017-01-25 02:19:32.29 190.04 SPECTOR4
IDLE 2017-01-25 02:19:32.29 2017-01-25 03:11:32.91 52.01 SPECTOR4
MAINTENANCE_GENERAL 2017-01-25 03:11:32.91 2017-01-25 18:31:44.26 920.18 SPECTOR4
我想获取此数据(第一行在凌晨 12 点分割,IntervalMin 更新为新的开始、停止时间):
StateName StartDT LastDT IntervalMin FullName
RUN_PARTS 2017-01-24 23:09:29.46 2017-01-25 00:00:00.00 50.30 SPECTOR4
RUN_PARTS 2017-01-25 00:00:00.00 2017-01-25 02:19:32.29 139.28 SPECTOR4
IDLE 2017-01-25 02:19:32.29 2017-01-25 03:11:32.91 52.01 SPECTOR4
MAINTENANCE_GENERAL 2017-01-25 03:11:32.91 2017-01-25 18:31:44.26 920.18 SPECTOR4
这有道理吗?我需要处理第一行穿过多个凌晨 12 点边界(即时间间隔超过 24 小时)的情况。
读了一堆东西后,看起来递归 CTE 应该能够做到这一点,但是,我无法理解这一点。
我特别提到这个例子,因为它接近我想做的事情:
Split row based on start end date SQL Server
为了更清楚起见,这里是生成我尝试拆分的数据的内容:
declare @STARTDT as datetime2
declare @STOPDT as datetime2
declare @CNAME as VARCHAR(70)
SET @STARTDT = DATEADD(d, -30, CURRENT_TIMESTAMP)
SET @STOPDT = CURRENT_TIMESTAMP
SET @CNAME = 'Spector4'
SELECT
CoatingChamberStates.Name
,CCSL.StartDT as StartDT
,CCSL.LastDT as LastDT
,CCSL.IntervalMin
,CoatingChambers.FullName
FROM CoatingChamberStateLogs as CCSL
INNER JOIN CoatingChamberStates on CCSL.CoatingChamberStatesID = CoatingChamberStates.CoatingChamberStatesID
INNER JOIN CoatingChambers on CCSL.CoatingChambersID = CoatingChambers.CoatingChambersID
where CCSL.StartDT >= @STARTDT
and CCSL.LastDT <= @STOPDT
and CoatingChambers.FullName = @CNAME
或者,如果您对如何解决这个问题有更好的想法,我将不胜感激。我的目标是评估并找到 SSRS 的限制,但我认为这种递归 CTE 可以解决当前的限制。
谢谢!
最佳答案
这是一种方法。如果您可以生成包含所有可能日期的日期表,这会更容易。然后,您可以将其与现有表连接
,以便根据case
表达式逻辑拆分行(如果行跨越多天)。
with dates(dt) as (select '2017-01-24' union all select '2017-01-25' union all select '2017-01-26' union all select '2017-01-27')
--This just uses the dates from the example in question
/*To generate dates for a given timeframe (for example all dates in 2017), use
with dates(dt) as (select '2017-01-01'
union all
select dateadd(day,1,dt) from dates where dt < '2017-12-31')
*/
select t.statename
,case when t.startdt>=d.dt then t.startdt else d.dt end as startdt
,case when datediff(day,lastdt,dt)=0 then t.lastdt else dateadd(day,1,d.dt) end as lastdt
,datediff(millisecond
,case when t.startdt>=d.dt then t.startdt else d.dt end
,case when datediff(day,lastdt,dt)=0 then t.lastdt else dateadd(day,1,d.dt) end)/60000.0
as split_diff
,t.fullname
from t
join dates d on d.dt >= cast(t.startdt as date) and d.dt<=cast(t.lastdt as date)
关于sql - 按日期时间/递归 CTE 将行拆分到 bin?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42032497/