1

我需要在 sql 下执行 12 个月(Apr12,May12,Jun12...Apr13) 但不想多次执行或重写我的 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'
4

2 回答 2

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
于 2013-06-11T07:15:39.913 回答
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
于 2013-06-11T06:11:29.997 回答