我想要实现的是在一个时间线中计算出现次数,将重叠事件视为单个事件,从这样的字段开始并使用TSQL:
Pattern (JSON array of couple of values indicating
the start day and the duration of the event)
----------------------------------------------------
[[0,22],[0,24],[18,10],[30,3]]
----------------------------------------------------
对于此示例,预期结果应为30
我需要的是一个TSQL函数来获取这个数字......
即使我不确定它是正确的路径,我也试图在我的数据集行之间模拟一种BINARY OR。 经过一番尝试后,我设法将我的数据集变成了这样的东西:
start | length | pattern
----------------------------------------------------
0 | 22 | 1111111111111111111111
0 | 24 | 111111111111111111111111
18 | 10 | 000000000000000001111111111
30 | 3 | 000000000000000000000000000000111
----------------------------------------------------
但是现在我没有'知道如何在TSQL中继续=) 我所说的解决方案可能是"模式之间的二进制OR#34;字段来获得这样的东西:
1111111111111111111111...........
111111111111111111111111.........
000000000000000001111111111......
000000000000000000000000000000111
--------------------------------------
111111111111111111111111111000111
是否可以在TSQL中执行此操作?
也许我只是让这里的事情复杂化你还有其他想法吗?
别忘了我只需要结果号!!!
谢谢大家
答案 0 :(得分:3)
只需要返回事件发生的总天数。
但我想知道实际计算二进制OR'd模式有多难。
declare @T table (start int, length int);
insert into @T values
(0,22),
(0,24),
(18,10),
(30,3);
WITH
DIGITS as (
select n
from (values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) D(n)
),
NUMBERS as (
select (10*d2.n + d1.n) as n
from DIGITS d1, DIGITS d2
where (10*d2.n + d1.n) < (select max(start+length) from @T)
),
CALC as (
select N.n, max(case when N.n between IIF(T.start>0,T.start,1) and IIF(T.start>0,T.start,1)+T.length-1 then 1 else 0 end) as ranged
from @T T
cross apply NUMBERS N
group by N.n
)
select SUM(c.ranged) as total,
stuff(
(
select ranged as 'text()'
from CALC
order by n
for xml path('')
),1,1,'') as pattern
from CALC c;
结果:
total pattern
30 11111111111111111111111111100111
答案 1 :(得分:2)
根据您的输入日期,您应该可以执行以下操作来计算您的活动天数。
cte
用于生成日期表,其开始和结束由两个日期变量定义。这些最适合作为源数据驱动的数据。如果必须使用编号的日期值,则只需返回递增的数字而不是递增日期:
declare @Events table (StartDate date
,DaysLength int
)
insert into @Events values
('20160801',22)
,('20160801',24)
,('20160818',10)
,('20160830',3)
declare @StartDate date = getdate()-30
,@EndDate date = getdate()+30
;with Dates As
(
select DATEADD(day,1,@StartDate) as Dates
union all
select DATEADD(day,1, Dates)
from Dates
where Dates < @EndDate
)
select count(distinct d.Dates) as EventingDays
from Dates d
inner join @Events e
on(d.Dates between e.StartDate and dateadd(d,e.DaysLength-1,e.StartDate)
)
option(maxrecursion 0)