TSQL中的二元运算符OR?

时间:2016-08-24 11:11:15

标签: sql-server tsql binary-data

我想要实现的是在一个时间线中计算出现次数,将重叠事件视为单个事件,从这样的字段开始并使用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中执行此操作?

也许我只是让这里的事情复杂化你还有其他想法吗?

别忘了我只需要结果号!!!

谢谢大家

2 个答案:

答案 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)