问题:
在数据库脚本开发中,有时需要生成一堆连续数字或者日期,例如yearly report就需要连续数字做年份,例如daily report就需要生成一定时间范围内的每一天日期。
而自带的系统表master..spt_values存在一定的局限性,只是从0到2047(验证脚本:select * from master..spt_values b where b.type = 'P'),也不能直接生成连续日期。
可能大部分人会想到一个笨办法,通过while循环去逐条插入数据到临时表,每次数字加1或者日期加1天,但这样和数据库服务器的交互就太频繁了。如果生成1W个连续数字,那就要跟数据库服务器交互1W次,可怕!如果是有1000个客户端都需要调用这个while循环,那就是1000W次!可怕!

解决方案:
可以使用公用表表达式CTE通过递归方式实现,并编写为一个通用表值函数方便调用,封装起来简化使用,返回表格式数据。
CTE是在内存中准备好数据,而不是每次一条往返服务器和客户端一次。如果需要再插入到临时表的话就是全部数据一次性插入。
如果传入参数为数字,则生成连续数字;如果传入参数为日期,则生成连续日期。
是不是觉得很方便呢?

函数脚本:

if object_id('dbo.fun_ConcatStringsToTable') is not null drop function dbo.fun_ConcatStringsToTable
go
/*
功能:连续字符串(数字或日期)以table形式返回
作者:zhang502219048 2018-12-10
脚本来源:https://www.cnblogs.com/zhang502219048/p/11108991.html
-- 示例1(数字):
select * from dbo.fun_ConcatStringsToTable(1, 10000)
-- 示例2(数字文本):
select * from dbo.fun_ConcatStringsToTable('1', '10000')
-- 示例3(日期):
declare @dateBegin datetime = '2009-1-1', @dateEnd datetime = '2018-12-31'
select * from dbo.fun_ConcatStringsToTable(@dateBegin, @dateEnd)
-- 示例4(日期文本):
select * from dbo.fun_ConcatStringsToTable('2009-1-1', '2018-12-31')
**/
create function [dbo].[fun_ConcatStringsToTable]
(
@strBegin as nvarchar(100),
@strEnd as nvarchar(100)
)
returns @tempResult table (vid nvarchar(100))
as
begin
--数字
if isnumeric(@strBegin) = 1 and isnumeric(@strEnd) = 1
begin
--使用CTE递归批量插入数字数据
;with cte_table(id) as
(
select cast(@strBegin as int)
union all
select id + 1
from cte_table
where id < @strEnd
)
insert into @tempResult
select cast(id as nvarchar(100))
from cte_table
option (maxrecursion 0)
end
--日期
else if isdate(@strBegin) = 1 and isdate(@strEnd) = 1
begin
--使用CTE递归批量插入日期数据
;with cte_table(CreatedDate) as
(
select cast(@strBegin as datetime)
union all
select dateadd(day, 1, CreatedDate)
from cte_table
where CreatedDate < @strEnd
)
insert into @tempResult
select convert(varchar(10), CreatedDate, 120)
from cte_table
option (maxrecursion 0)
end return;
end
go

调用函数示例:

-- 示例1(数字):
select * from dbo.fun_ConcatStringsToTable(1, 10000)
-- 示例2(数字文本):
select * from dbo.fun_ConcatStringsToTable('', '')
-- 示例3(日期):
declare @dateBegin datetime = '2009-1-1', @dateEnd datetime = '2018-12-31'
select * from dbo.fun_ConcatStringsToTable(@dateBegin, @dateEnd)
-- 示例4(日期文本):
select * from dbo.fun_ConcatStringsToTable('2009-1-1', '2018-12-31')

脚本运行结果:

     

结论:
从上面几个图可以看到,通过简单调用fun_ConcatStringsToTable这个自定义表值函数,指定起止数字或日期,就达到了生成连续数字和日期的目的。

扩展:
如果想生成连续月份呢?博主在这里也帮大家写了一下脚本,如果需要可以在此基础上再自行做成表值函数:

with cte_table(CreatedDate) as
(
select cast('2017-12-1' as datetime)
union all
select dateadd(month, 1, CreatedDate)
from cte_table
where CreatedDate < '2018-04-01'
)
select convert(varchar(7), CreatedDate, 120) as YearMonth
from cte_table
option (maxrecursion 0)

【转载请注明博文来源:https://www.cnblogs.com/zhang502219048/p/11108991.html

sql server使用公用表表达式CTE通过递归方式编写通用函数自动生成连续数字和日期的更多相关文章

  1. SQL Server中公用表表达式 CTE 递归的生成帮助数据,以及递归的典型应用

    本文出处:http://www.cnblogs.com/wy123/p/5960825.html 我们在做开发的时候,有时候会需要一些帮助数据,必须需要连续的数字,连续间隔的时间点,连续的季度日期等等 ...

  2. SQL Server温故系列(3):SQL 子查询 & 公用表表达式 CTE

    1.子查询 Subqueries 1.1.单行子查询 1.2.多行子查询 1.3.相关子查询 1.4.嵌套子查询 1.5.子查询小结及性能问题 2.公用表表达式 CTE 2.1.普通公用表表达式 2. ...

  3. SQL Server 公用表表达式(CTE)实现递归

    公用表表达式简介: 公用表表达式 (CTE) 可以认为是在单个 SELECT.INSERT.UPDATE.DELETE 或 CREATE VIEW 语句的执行范围内定义的临时结果集.CTE 与派生表类 ...

  4. SQL Server 公用表表达式(CTE)实现递归的方法

    公用表表达式简介: 公用表表达式 (CTE) 可以认为是在单个 SELECT.INSERT.UPDATE.DELETE 或 CREATE VIEW 语句的执行范围内定义的临时结果集.CTE 与派生表类 ...

  5. 公用表表达式 (CTE)、递归、所有子节点、sqlserver

    指定临时命名的结果集,这些结果集称为公用表表达式 (CTE).公用表表达式可以包括对自身的引用.这种表达式称为递归公用表表达式. 对于递归公用表达式来说,实现原理也是相同的,同样需要在语句中定义两部分 ...

  6. 公用表表达式 (CTE)、递归

    指定临时命名的结果集,这些结果集称为公用表表达式 (CTE).公用表表达式可以包括对自身的引用.这种表达式称为递归公用表表达式. 对于递归公用表达式来说,实现原理也是相同的,同样需要在语句中定义两部分 ...

  7. SQL Server CET 通用表表达式 之 精典递归

    SQL2005 Common Table Expressions(CET)即通用表表达式. SQLSERVER CET递归使用案例: 1.普通案例 表结构如下:   ;WITH cet_depart ...

  8. 公用表表达式CTE简单递归使用-简单树形结构

    1.建表脚本 CREATE TABLE [dbo].[tb_tree]( ,) NOT NULL, [ParentId] [int] NULL, ) NULL, CONSTRAINT [PK_tb_t ...

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

    本文的作者辛苦了,版权问题特声明本文出处:http://www.cnblogs.com/wy123/p/5960825.html 工作有时候会需要一些帮助数据,必须需要连续的数字,连续间隔的时间点,连 ...

随机推荐

  1. la4080 Warfare And Logistics 罗列+最短

    为了图.计算最短随机分ans1.和删除边缘.免费才能够获得最大和短路之间的最大分ans2,如果这两个不沟通.看作是两个点之间的最短距离l. 第一个想法是枚举每个边缘,然后运行n最短时间.但是,这种复杂 ...

  2. HDU - 4734 F(x) (2013成都网络游戏,数字DP)

    意甲冠军:求0-B见面<=F[A]所有可能的 思维:数字DP,内存搜索 #include <iostream> #include <cstring> #include & ...

  3. 在Eclipse安装ADT

    Eclipse 3.4 (Ganymede) 启动 Eclipse,然后选择 Help > Software Updates….在出现的对话框中.单击 Available Software 选项 ...

  4. N+1:创新点的设计

    定义.公式.模型.算法的提出: 0. 如何进行抽象,如何定义数学表达式 二次衰减函数: f(z)=1z2 ⇒ f(z)=11+z2 噪声衰减因子: 对值域的要求,单调性的要求,必须是可调的: 2n1+ ...

  5. [视频]mac系统下虚拟机parallels安装ubuntu 14.04视频教程

    此文是http://www.mr-wu.cn/install-ubuntu-14-04-on-parallels-for-mac/这篇博文的补充,为整个ubuntu 14.04安装过程的视频录像. m ...

  6. Nginx http filter异常排查

    问题: 访问异常 root@cloud:/usr/local/nginx# curl -i http://localhost/test.html curl: (52) Empty reply from ...

  7. 终端开发补充 : 读 curses模块官方文档...

    curses是一个提供终端屏幕打印和键盘处理的库, 我个人的理解就是终端里的gui(当然它是基于文本的)... 写2048的时候用到了这个库, 所以现在过来好好研究一下这个库... 下面是文档内容 : ...

  8. WPF后台生成datatemplate(TreeViewItem例子)

    public void loadCheckListDataTemplate(TreeViewItem tvi) { DataTemplate cdt = new DataTemplate(); Fra ...

  9. Win10《芒果TV》商店内测版更新至v3.1.6:率先支持Xbox One平台 - 参与反馈,赢取VIP奖励

    芒果TV For Win10商店内测版 v3.1.6 于2016年9月1日星期四下午正式登陆商店 主要是优化手机版视频下载相关设置.策略.风险提示,并升级兼容目标,率先支持Xbox One平台,覆盖更 ...

  10. Ubuntu服务器搭建

    Ubuntu16 搭建Git 服务器 - 濮成林 - 博客园 https://www.cnblogs.com/charliePU/p/7528226.html Ubuntu 搭建 GitLab 笔记 ...