SQL Server中公用表表达式 CTE 递归的生成帮助数据,以及递归的典型应用
2016-10-14 16:03
501 查看
本文出处:http://www.cnblogs.com/wy123/p/5960825.html
我们在做开发的时候,有时候会需要一些帮助数据,必须需要连续的数字,连续间隔的时间点,连续的季度日期等等
常见很多人利用master库的spt_values系统表,这个当然没有问题
比如下面这个(没截完,结果是0-2047)
这样也可以使用,但是感觉不够灵活,一是不是随便一个账号都可以访问master数据库的,而是他这里面也只有这么一个连续的数字了,
想要别的结果集就不太弄了,
类似数据可以用公用表表达式CTE的递归来生成
比如上述的0-2047的结果集
可以直接让CTE参数逻辑运算,也可以生成临时表,达到多次重用的目的,这样感觉是不是也很清爽?
1,生成连续数字(当然数字的起始值,间隔值都可以自定义)
2,CTE递归生成连续日期
3,生成连续间隔的时间点
有时候一些统计需要按照一个小时或者半个小时之类的时间间隔做组合,比如统计某天内没半个小时的小时数据等等
当然这里就可以非常灵活了,更骚一点的变形
4,生成连续季度的最后一天
通过变形可以生成两个日期间隔之间的的数据
需要注意的是,CTE递归的默认次数是100,如果不指定递归次数(option (maxrecursion N);),超出默认最大递归次数之后会报错。
——————————————递归原本很容易使用,本文原本是说用递归生成帮助数据的,有朋友问到递归本身的使用,那就再补充一个DEMO吧———————————————————
补充园友的一个实际应用-20161119
测试数据:
原始数据的样子,很普通
创建一个函数,获取当前节点的父节点信息
实际效果:
总结:本文演示了几种常用的根据CTE递归生成帮助数据的情况,如果需要帮助数据,可以根据CTE的递归特性做灵活处理。
我们在做开发的时候,有时候会需要一些帮助数据,必须需要连续的数字,连续间隔的时间点,连续的季度日期等等
常见很多人利用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
需要注意的是,CTE递归的默认次数是100,如果不指定递归次数(option (maxrecursion N);),超出默认最大递归次数之后会报错。
——————————————递归原本很容易使用,本文原本是说用递归生成帮助数据的,有朋友问到递归本身的使用,那就再补充一个DEMO吧———————————————————
补充园友的一个实际应用-20161119
测试数据:
create table ProuctInfo ( Id INT, ParentId INT, ProuctName VARCHAR(50) ) INSERT INTO ProuctInfo VALUES (1,0,'镜片') INSERT INTO ProuctInfo VALUES (2,0,'镜架') INSERT INTO ProuctInfo VALUES (101,1,'高级镜片') INSERT INTO ProuctInfo VALUES (102,1,'普通镜片') INSERT INTO ProuctInfo VALUES (201,2,'高级镜架') INSERT INTO ProuctInfo VALUES (202,2,'普通镜架') INSERT INTO ProuctInfo VALUES (1001,101,'高级镜片1') INSERT INTO ProuctInfo VALUES (1002,102,'普通镜片2') INSERT INTO ProuctInfo VALUES (2001,201,'高级镜架1') INSERT INTO ProuctInfo VALUES (2002,202,'普通镜架2')
原始数据的样子,很普通
创建一个函数,获取当前节点的父节点信息
CREATE FUNCTION dbo.FnGetParentInfo(@id int) returns varchar(max) as begin declare @name varchar(max) --查询某一个节点的所有父节点 ;with SubTab as ( select [ID],[ParentID], cast(ProuctName as varchar(200)) as ProuctName from ProuctInfo WHERE Id = @id union all select a.[ID],a.[ParentID],cast(a.ProuctName+'--->'+b.ProuctName as varchar(200)) as ProuctName from ProuctInfo a,SubTab b where a.[ID]=b.[ParentID] ) select @name = ProuctName from SubTab where ParentId = 0 return @name end
实际效果:
总结:本文演示了几种常用的根据CTE递归生成帮助数据的情况,如果需要帮助数据,可以根据CTE的递归特性做灵活处理。
相关文章推荐
- SQL Server 2008空间数据应用系列十:使用存储过程生成GeoRSS聚合空间信息
- SQLSERVER应用:公用表表达式(CTE)的递归调用
- SQL SERVER 2005 公用表表达式(CTE)处理递归(父子关系)
- SQL Server 公用表表达式(CTE)实现递归的方法
- SQL Server 查询数据库的表结构以及描述来生成数据字典
- SQL Server 2008空间数据应用系列十:使用存储过程生成GeoRSS聚合空间信息
- 关于SQL SERVER 公用表达式CTE应用递归时的模型个人的理解
- sqlserver 2005 公用表表达式CTE与 ORACLE递归生成树查询 对比
- SQL Server 2008空间数据应用系列十:使用存储过程生成GeoRSS聚合空间信息
- SQL Server 公用表表达式(CTE)实现递归
- SQL Server 公用表表达式(CTE)实现递归
- sql server 数据库修复,mdf 损坏 修复 直接从物理文件 抽取数据 生成新的数据库
- 视频大数据技术的应用以及存在的隐私泄露问题
- SQL Server培训录像(以及其他好的数据教程的指针)
- 公用表表达式 (CTE)、递归
- 大数据在京东的典型应用:京东用户画像技术曝光
- 第三百七十七节,Django+Xadmin打造上线标准的在线教育平台—apps目录建立,以及数据表生成
- SQL SERVER公用表表达式 (CTE)的用法和运用场景
- GridView应用技巧------如何在没数据的时候显示表格以及填充空白行
- 从sql server 2012生成带数据脚本