【问题标题】:Binary operator OR in TSQL?SQL中的二元运算符OR?
【发布时间】:2016-08-24 11:11:14
【问题描述】:

我想要实现的是在某种时间线上计算发生次数,将重叠事件视为一个事件,从这样的字段开始并使用 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 中进行 =) 我所说的解决方案可能是“模式”字段之间的二进制或以获得类似的东西:

1111111111111111111111...........
111111111111111111111111.........
000000000000000001111111111......
000000000000000000000000000000111
--------------------------------------
111111111111111111111111111000111

在 TSQL 中可以做到吗?

也许我只是把事情复杂化了,你还有其他想法吗?

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

谢谢大家

【问题讨论】:

  • 那么您的预期结果是举办活动的总天数?
  • 我预计至少举办一次活动的总天数!
  • 这里的预期输出是什么?
  • 我的字段“pattern”现在是一个varchar.....我尝试将值转换为二进制并使用运算符 | ...但没有成功
  • @KannanKandasamy 你读过问题吗? 对于这个例子,预期的结果应该是 30

标签: sql-server tsql binary-data


【解决方案1】:

只需要返回事件发生的总天数。

但我想知道实际计算二进制 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

【讨论】:

  • 我无法让它在 sql-2008 的生产环境中工作,但感谢您分享您有趣的解决方案!
【解决方案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)

【讨论】:

  • 有趣的代码,它就像我尝试使用我的真实数据集一样工作,但我遇到了一个小问题!是否有可能超过 100 次递归的限制?
  • 对不起,我找到了 OPTION (maxrecursion 140)
  • @Zakkojo 如果您正确设置了开始和结束日期,您也可以简单地将maxrecursion 设置为0 以完全不受限制。
猜你喜欢
  • 2015-07-08
  • 1970-01-01
  • 1970-01-01
  • 2014-05-05
  • 2019-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-14
相关资源
最近更新 更多