2015-10-14 91 views
-1

[myTable]有2个日期类型列:startD和endD,以及其他列类型。我想看看2015年的每一天都包含在区间[startD,结束]内统计一年中有多少天属于一个区间

declare @t table (A date, B date) 
    insert into @t (A,B) 
    select distinct startD, endD 
    from myTable 


    declare @start date = '2015-01-01' 
    while @start < '2016-01-01' 
    begin 
    select 
    case 
     when @start >= @t.A and @start <= @t.B 
      then 1 
      else 0 
     end as it 
    from @t 
    set @start = DateAdd(day,1,@start) 
    end 

此外,另一个问题:比方说,我想算10值多少都在365值。考虑到上面的代码,我该如何做到这一点?

如果我改变t@t我得到Must declare the scalar variable "@t".

+0

你在哪看到'多部分标识符无法绑定'错误? – qxg

+0

我在哪里添加注释行 –

+1

你想实现什么?我有一种感觉,就是打印'0s'和'1s'不是你的目标。 –

回答

0

不能使用

if @start >= t.A and @start <= t.B -- how can I reffer to t.A and t.B ? 

尝试这样

select case when @start >= A and @start <=B then 1 else 0 end as result 
from @t 

之后,你可以打印所有的结果值一个一个。

,或者

(希望)解决方案:(我不知道你真正想要的是什么,还不清楚,但希望这会 帮助你)

declare @start date = '2015-01-01' 
declare @end date = '2016-01-01' 

    select case when (A>[email protected] and A<@end) and (b>=A and B<[email protected]) then 1 else 0 end as result 
     from @t 

如果它不是你在找什么,那么你只需要在case条件下更改 逻辑。

0

可以使用DATEDIFF数天:

SELECT IIF(y.days >=0, y.days + 1, 0) AS numOfDays 
FROM mytable 
CROSS APPLY (
    SELECT IIF('20150101' > startD, '20150101', startD), 
     IIF('20151231' < endD, '20151231', endD)) AS x([from],[to]) 
CROSS APPLY (SELECT DATEDIFF(d, x.[from], x.[to])) AS y(days)   

上述查询计算包含在您的表的区间内[startD, end] 2015年的天数。

Demo here

+0

mytable可以包含startD/endD的重复项,例如:2015-01-01(startD) - 2015-02-01(endD)和2015-01-01(startD) - 2015-02-02(endD)。我应该考虑一个独特的过滤器? –

+0

我用你的代码来处理我的情况,结果是20k行。 Mytable包含1750行。 –

+0

@FlorinM。我的查询为原始表的每一行返回一行。你能设置一个sqlfiddle来证明你提到的问题吗? –

0

根据您的要求:

我想看看2015年的每一天都是内部包含的 间隔

你可以的帮助下做到这一点a Tally Table:

SQL Fiddle

--Prepare sample data 
DECLARE @t TABLE(startD DATE, endD DATE) 
INSERT INTO @t VALUES 
('20150101', '20150125'), 
('20150301', '20150313'); 

DECLARE @year INT = 2015 
DECLARE @numberOfDays INT 

SELECT @numberOfDays = DATEDIFF(DAY, DATEADD(YEAR, @year - 1900, 0), DATEADD(YEAR, @year + 1 - 1900, 0)) 

;WITH E1(N) AS(
    SELECT 1 FROM(VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))t(N) 
), 
E2(N) AS(SELECT 1 FROM E1 a CROSS JOIN E1 b), 
E4(N) AS(SELECT 1 FROM E2 a CROSS JOIN E2 b), 
Tally(N) AS(
    SELECT TOP(@numberOfDays) 
     ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) 
    FROM E4 
), 
CteAllDates(dt) AS(
    SELECT 
     CAST(DATEADD(DAY, N-1, DATEADD(YEAR, @year - 1900, 0)) AS DATE) 
    FROM Tally 
) 
SELECT 
    [Date]   = d.dt, 
    [Is_In_Interval] = CASE WHEN t.startD IS NULL THEN 0 ELSE 1 END 
FROM CteAllDates d 
LEFT JOIN @t t 
    ON d.dt BETWEEN t.startD AND t.endD