• SQL点点滴滴_公用表表达式(CTE)递归的生成帮助数据


    本文的作者辛苦了,版权问题特声明本文出处http://www.cnblogs.com/wy123/p/5960825.html

    工作有时候会需要一些帮助数据,必须需要连续的数字,连续间隔的时间点,连续的季度日期等等。常见很多人利用master库的spt_values系统表。

    比如下面这个(没截完,结果是0-2047)

    这样也可以使用,但是感觉不够灵活,一不是随便一个账号都可以访问master数据库的,另外一个这里面也只有这么一个连续的数字了,想要别的结果集就不太弄。
    类似数据可以用公用表表达式CTE的递归来生成,比如上述的0-2047的结果集

    复制代码
    ;with GenerateHelpData
    as
    (
        select 0 as id
        union all
        select id+1 from GenerateHelpData where id<2047
    )
    select id from GenerateHelpData option (maxrecursion 2047);
    复制代码

    可以直接让CTE参数逻辑运算,也可以生成临时表,达到多次重用的目的。

    1、生成连续数字(当然数字的起始值,间隔值都可以自定义)

    复制代码
    --生成连续数字
    ;with GenerateHelpData
    as
    (
        select 0 as id
        union all
        select id+1 from GenerateHelpData where id<2047
    )
    select id from GenerateHelpData option (maxrecursion 2047);
    复制代码

    2、CTE递归生成连续日期

    复制代码
    --生成连续日期
    ;with GenerateHelpData
    as
    (
        select cast('2016-10-01' as date) as [Date]
        union all
        select DATEADD(D,1,[Date]) from GenerateHelpData where [Date]<'2017-01-01'
    )
    select [Date] from GenerateHelpData;
    复制代码

    3、生成连续间隔的时间点

      有时候一些统计需要按照一个小时或者半个小时之类的时间间隔做组合,比如统计某天内没半个小时的小时数据等等

    复制代码
    --生成连续间隔的时间点
    ;with GenerateHelpData
    as
    (
        select 1 as id, cast('00:00:00' as time(0)) as timeSection
        union all
        select id+1 as id,  cast(dateadd(mi,30,timeSection) as time(0)) as timeSection 
         from GenerateHelpData  where id<49
    )
    select * from GenerateHelpData
    复制代码

    当然这里就可以非常灵活了,更骚一点的变形

    复制代码
    --更骚一点的变形
    ;with GenerateHelpData
    as
    (
        select 1 as id, cast('00:00:00' as time(0)) as timeSection
        union all
        select id+1 as id,  cast(dateadd(mi,30,timeSection) as time(0)) as timeSection 
         from GenerateHelpData  where id<49
    )
    select 
    A.timeSection as timeSectionFrom,
    B.timeSection as timeSectionTo,
    cast(A.timeSection as varchar(10))+'~'+cast(B.timeSection as varchar(10)) as timeSection
    from GenerateHelpData  A inner join GenerateHelpData B on A.id= B.id-1
    复制代码

    4、生成连续季度的最后一天

    复制代码
    DECLARE 
    @begin_date date = '2014-12-31',
    @end_date date = '2016-12-31'
    ;with GenerateHelpData as
    (
        select 
            CAST(    CASE 
                        WHEN RIGHT(@begin_date,5)='12-30' 
                    THEN DATEADD(DAY,1,@begin_date) 
                        ELSE @begin_date 
                    END AS    DATE)
            AS EndingDate
        UNION ALL
        SELECT     
            CASE WHEN RIGHT(DATEADD(QQ,1,EndingDate),5)='12-30' 
            THEN  DATEADD(DAY,1,DATEADD(QQ,1,EndingDate)) 
            ELSE DATEADD(QQ,1,EndingDate)
            END AS EndingDate
        from GenerateHelpData where EndingDate< @end_date
    )
    select * from GenerateHelpData
    复制代码

    通过变形可以生成两个日期间隔之间的的数据

    复制代码
    DECLARE 
    @begin_date date = '2014-12-31',
    @end_date date = '2016-12-31'
    ;with GenerateHelpData as
    (
        select 1 as id ,
            CAST(    CASE 
                        WHEN RIGHT(@begin_date,5)='12-30' 
                    THEN DATEADD(DAY,1,@begin_date) 
                        ELSE @begin_date 
                    END AS    DATE)
            AS EndingDate
        UNION ALL
        SELECT     id+1 as id,
            CASE WHEN RIGHT(DATEADD(QQ,1,EndingDate),5)='12-30' 
            THEN  DATEADD(DAY,1,DATEADD(QQ,1,EndingDate)) 
            ELSE DATEADD(QQ,1,EndingDate)
            END AS EndingDate
        from GenerateHelpData where EndingDate< @end_date
    )
    select 
    A.EndingDate as DateFrom,
    B.EndingDate as DateTo,
    cast(A.EndingDate as varchar(10))+'~'+cast(B.EndingDate as varchar(10)) as timeSection
    from GenerateHelpData  A inner join GenerateHelpData B on A.id= B.id-1
    复制代码

    需要注意的是:

    1、CTE递归的默认次数是100,如果不指定递归次数(option (maxrecursion N);),超出默认最大递归次数之后会报错。

    2、指定了最大递归次数以后,超出最大递归次数也会报错。

     

     总结:本文演示了几种常用的根据CTE递归生成帮助数据的情况,如果需要帮助数据,可以根据CTE的递归特性做灵活处理。

  • 相关阅读:
    Sum of a Function(区间筛)
    (01背包)输出方案数
    删边求概率
    完全背包输出方案数(dp)
    二分
    Just Arrange the Icons(模拟)
    Balls of Buma(回文串)
    dp思想
    刷题-力扣-190. 颠倒二进制位
    刷题-力扣-173. 二叉搜索树迭代器
  • 原文地址:https://www.cnblogs.com/Zeros/p/5961308.html
Copyright © 2020-2023  润新知