SQL Server中公用表表达式 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
需要注意的是,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中公用表表达式 CTE 递归的生成帮助数据,以及递归的典型应用的更多相关文章
- sql server使用公用表表达式CTE通过递归方式编写通用函数自动生成连续数字和日期
问题:在数据库脚本开发中,有时需要生成一堆连续数字或者日期,例如yearly report就需要连续数字做年份,例如daily report就需要生成一定时间范围内的每一天日期.而自带的系统表mast ...
- SQL Server温故系列(3):SQL 子查询 & 公用表表达式 CTE
1.子查询 Subqueries 1.1.单行子查询 1.2.多行子查询 1.3.相关子查询 1.4.嵌套子查询 1.5.子查询小结及性能问题 2.公用表表达式 CTE 2.1.普通公用表表达式 2. ...
- SQL Server 公用表表达式(CTE)实现递归
公用表表达式简介: 公用表表达式 (CTE) 可以认为是在单个 SELECT.INSERT.UPDATE.DELETE 或 CREATE VIEW 语句的执行范围内定义的临时结果集.CTE 与派生表类 ...
- SQL Server 公用表表达式(CTE)实现递归的方法
公用表表达式简介: 公用表表达式 (CTE) 可以认为是在单个 SELECT.INSERT.UPDATE.DELETE 或 CREATE VIEW 语句的执行范围内定义的临时结果集.CTE 与派生表类 ...
- SQL Server进阶(六)表表达式--派生表、公用表表达式(CTE)、视图和内联表值函数
概述 表表达式是一种命名的查询表达式,代表一个有效地关系表.可以像其他表一样,在数据处理中使用表表达式. SQL Server支持四种类型的表表达式:派生表,公用表表达式,视图和内联表值函数. 为什么 ...
- SQL Server 表表达式--派生表、公用表表达式(CTE)、视图和内联表值函数
概述 表表达式是一种命名的查询表达式,代表一个有效地关系表.可以像其他表一样,在数据处理中使用表表达式. SQL Server支持四种类型的表表达式:派生表,公用表表达式,视图和内联表值函数. 为什么 ...
- SQL点点滴滴_公用表表达式(CTE)递归的生成帮助数据
本文的作者辛苦了,版权问题特声明本文出处:http://www.cnblogs.com/wy123/p/5960825.html 工作有时候会需要一些帮助数据,必须需要连续的数字,连续间隔的时间点,连 ...
- 公用表表达式 (CTE)、递归、所有子节点、sqlserver
指定临时命名的结果集,这些结果集称为公用表表达式 (CTE).公用表表达式可以包括对自身的引用.这种表达式称为递归公用表表达式. 对于递归公用表达式来说,实现原理也是相同的,同样需要在语句中定义两部分 ...
- 公用表表达式 (CTE)、递归
指定临时命名的结果集,这些结果集称为公用表表达式 (CTE).公用表表达式可以包括对自身的引用.这种表达式称为递归公用表表达式. 对于递归公用表达式来说,实现原理也是相同的,同样需要在语句中定义两部分 ...
随机推荐
- tomcat相关
一.下面这篇文章介绍了tomcat log相关内容 http://blog.csdn.net/cowmich/article/details/8173005
- DPC和ISR的理解
首先来说中断 计算机的中断分为软中断和硬中断,即IRQL和DIRQL,共32个级别,从0~31级别依次提升,0~2属于软中断 一般线程运行于PASSIVE_LEVEL级别,如果不想在运行时切换到其他线 ...
- 【转】ubuntu下最好用的输入法fcitx-sunpinyin
http://www.freetstar.com/index.php/ubuntu-most-use-friendly-fcitx-sunpinyin 今天难得折腾一会儿输入法,对于系统美化方面的 ...
- FFT时域与频域的关系,以及采样速率与采样点的影响
首先对于FFT来说,输入的信号是一个按一定采样频率获得的信号序列,而输出是每个采样点对应的频率的幅度(能量). 下面详细分析: 在FFT的输出数据中,第一个值是直流分量的振幅(这样对应周期有无穷的可能 ...
- 为首次部署MongoDB做好准备:容量计划和监控
如果你已经完成了自己新的MongoDB应用程序的开发,并且现在正准备将它部署进产品中,那么你和你的运营团队需要讨论一些关键的问题: 最佳部署实践是什么? 为了确保应用程序满足它所必须的服务层次我们需要 ...
- 关于EF6的记录Sql语句 与 EntityFramework.Extend 的诟病
1.关于EF6的记录Sql语句,一个老生长谈的问题. 他生成的sql语句实在是烂,大家都这样说 2.EF6 更新删除不方便,没有批量操作.所以,有人出了EF6.Extend 大家用起来也很爽 基于以 ...
- 关于大型网站技术演进的思考(十九)--网站静态化处理—web前端优化—上(11)
网站静态化处理这个系列马上就要结束了,今天我要讲讲本系列最后一个重要的主题web前端优化.在开始谈论本主题之前,我想问大家一个问题,网站静态化处理技术到底是应该归属于web服务端的技术范畴还是应该归属 ...
- awk神器
序 产品经理(PM)过来找你要最近某某的数据,而你知道这些数据目前只能通过日志文件去分析,因为我们知道,我们不可能把所有数据都放入db中(这不科学啊!).每当有这样任务的时候,你就用php或j ...
- Express4 启航指南
确实有感而发,Nodejs真的发展太快了,这么说的原因有两点:自己去年冬天买了本<了不起的Node.js>,里面介绍Express的版本还是2.x.x:前些天小伙伴买了本<Node. ...
- I/O重定向的原理和实现
在Unix系统中,每个进程都有STDIN.STDOUT和STDERR这3种标准I/O,它们是程序最通用的输入输出方式.几乎所有语言都有相应的标准I/O函数,比如,C语言可以通过scanf从终端输入字符 ...