这个sql的递归cte可能

时间:2013-06-10 22:17:02

标签: sql sql-server sql-server-2008

我需要在sql下执行12个月(4月12日,5月12日,6月12日... 4月13日) 但是不想多次执行或重写我的sql。试图确定是否有办法做这个作为递归cte的一部分..需要确保月份日期是正确的(每隔一个月30/31天,2月有28天)。

这是我的sql

Select 
--Month of Apr 2012
    (Select 1.0 * 100 *
        (
        Select COUNT(*)
        from B b 
        left outer join F f on f.id = b.id 
        Where f.date1 < '05/01/2012' and 
            (f.date2 between '04/01/2012' and '04/30/2012' or f.date2 is Null)
        )

        /
        (Select COUNT(*)
        from f
        Where date1 < '05/01/2012' and 
            (date2 between '04/01/2013' and '04/30/2013' or date2 is Null)) as 'Apr 2012',
--Month of May 2012
    (Select 1.0 * 100 *
        (
        Select COUNT(*)
        from B b 
        left outer join F f on f.id = b.id 
        Where f.date1 < '06/01/2012' and 
            (f.date2 between '05/01/2012' and '05/31/2012' or f.date2 is Null)
        )

        /
        (Select COUNT(*)
        from f
        Where date1 < '06/01/2012' and 
            (date2 between '05/01/2013' and '05/31/2013' or date2 is Null)) as 'May 2012'

2 个答案:

答案 0 :(得分:1)

试试这个 -

DECLARE @DateFrom DATETIME
SELECT @DateFrom = '20130101'

;WITH cte AS 
(
    SELECT 
          t.[date]
        , date_next
        , [month] = MONTH(t.[date])
        , [year] = YEAR(t.[date])
    FROM (
        SELECT 
              [date] = DATEADD(MONTH, sv.number, @DateFrom)
            , date_next = DATEADD(MONTH, sv.number + 1, @DateFrom)
        FROM [master].dbo.spt_values sv
        WHERE sv.[type] = 'p'
            AND sv.number BETWEEN 0 AND 11
    ) t
) 
SELECT 
      cte.[date]
    , value = 100 * t2.cnt / t.cnt 
FROM cte
OUTER APPLY (
    SELECT cnt = COUNT(1)
    FROM f
    WHERE f.date1 < cte.date_next
        AND cte.[month] = ISNULL(MONTH(f.date2), cte.[month])
        AND cte.[year] = ISNULL(YEAR(f.date2), cte.[year])
) t
OUTER APPLY (
    SELECT cnt = COUNT(1)
    FROM b 
    LEFT JOIN f on f.id = b.id 
    WHERE f.date1 < cte.date_next
        AND cte.[month] = ISNULL(MONTH(f.date2), cte.[month])
        AND cte.[year] = ISNULL(YEAR(f.date2), cte.[year])
) t2

答案 1 :(得分:0)

尝试此操作以生成所有月份的第一天和最后一天。另一种解决方案是使用包含这些信息的静态表。之后,您可以直接加入此表,并根据您的需要进行分组。

另外我不明白1.0 * 100如果你想确定你没有int那里你可以尝试100。

declare @year varchar(4)
select @year=convert(varchar(4),year(getdate()))

create table #months
(
FirstDay datetime
,LastDay datetime
)

declare @k int,@date datetime
select @k=1

while @k<=12
begin
select @date=convert(datetime,@year+right('0'+convert(varchar(2),@k),2)+'01',112)
insert into #months
select @date
        ,dateadd(d,-1,dateadd(m,1,@date))
set @k=@k+1
end

select *
from #months

drop table #months