得到一个时间段内连续日期查询(转)

本文介绍了一种使用SQL生成连续日期序列的方法,并通过示例展示了如何根据这些连续日期来汇总财务数据,包括收入、支出及余额等关键指标。

得到连续日期需要借助一个有连续序号的表,参考如何得到连续序号

--〉生成连续日期的方法
IF OBJECT_ID('tempdb..#t') IS NOT NULL  DROP TABLE #t
GO
create table #t(id int identity,Dt varchar(10))
go
declare  @starttime datetime,@endtime datetime
set @starttime = '2010-5-01'
set @endtime ='2010-5-31'


insert #t
select convert(varchar(10),dateadd(day,number,@starttime),120) dt
from master..spt_values
where type='P' and number between 0 and datediff(day,@starttime,@endtime)
--结果
select * from #t

/*
id          Dt
----------- ----------
1           2010-05-01
2           2010-05-02
3           2010-05-03
4           2010-05-04
5           2010-05-05
6           2010-05-06
7           2010-05-07
8           2010-05-08
9           2010-05-09
10          2010-05-10
11          2010-05-11
12          2010-05-12
13          2010-05-13
14          2010-05-14
15          2010-05-15
16          2010-05-16
17          2010-05-17
18          2010-05-18
19          2010-05-19
20          2010-05-20
21          2010-05-21
22          2010-05-22
23          2010-05-23
24          2010-05-24
25          2010-05-25
26          2010-05-26
27          2010-05-27
28          2010-05-28
29          2010-05-29
30          2010-05-30
31          2010-05-31

(31 行受影响)
*/

实际例子:

原帖:

http://topic.youkuaiyun.com/u/20100619/18/3b4d60f2-b477-414f-adec-569ccee3fec6.html

http://topic.youkuaiyun.com/u/20100619/15/367ed306-b8ea-4b2b-9614-2acd64c0e07e.html


根据开始时间,结束时间 生成连续的时间
然后在用这个连续的时间去比较表里的数据

if object_id('TZ_Money')is not null drop table TZ_Money go
create table TZ_Money
(
    Id
int identity(1,1) primary key,  
    Uid
varchar(8) not null,            --用户ID
    Income numeric(10,2) not null,        --收入
    Expenditure numeric(10,2) not null,           --支出
    Balance numeric(10,2) not null,        --余额
    [Time] datetime not null,            --日期(天为单位)
    LastTime datetime  null            --最后时间
)
go
set identity_insert TZ_Money on
insert TZ_Money (id,uid,Income,Expenditure,Balance,Time)
select 1 ,'abc1', 1.00 ,5.00 ,96 ,'2010-06-7 12:12:12' union all  
select 2 ,'abc1', 3.00 ,4.00, 95 ,'2010-06-7 21:12:45' union all 
select 3 ,'abc1', 4.00 ,50.00 ,49 ,'2010-08-7 09:45:59'

go

if object_id('p_test1')is not null drop proc p_test1
go
create proc p_test1 @starttime datetime,@endtime datetime,@type nvarchar(4)='',@uid varchar(8)
as
begin
   
declare @sql varchar(8000),@w varchar(1000),@g varchar(1000)
   
create table #t(id int identity,D varchar(10))

   
set @sql='select isnull(sum(Income),0.00) 收入,isnull(sum(Expenditure),0.00)支出,'
   
   
if @type=''
   
begin
       
insert #t
       
select convert(varchar(4),dateadd(year,number,@starttime),120)
       
from master..spt_values
       
where type='P' and number between 0 and datediff(year,@starttime,@endtime)

       
set @sql=@sql+'isnull((select top 1 Balance from TZ_Money where convert(varchar(4),[Time],120)<=a.d and Balance is not null   order by time desc),0.00) 余额,a.d as [time]'
       
set @sql=@sql+' from #t a left join TZ_Money t on a.d=convert(varchar(4),t.[Time],120)   '           
   
end   
   
if @type=''
   
begin
       
insert #t
       
select convert(varchar(7),dateadd(month,number,@starttime),120)
       
from master..spt_values
       
where type='P' and number between 0 and datediff(month,@starttime,@endtime)

       
set @sql=@sql+'isnull((select top 1 Balance from TZ_Money where convert(varchar(7),[Time],120)<=a.d and Balance is not null   order by time desc),0.00) 余额,a.d as [time]'
       
set @sql=@sql+' from #t a left join TZ_Money t on a.d=convert(varchar(7),t.[Time],120)   '
   
end
   
if @type=''
   
begin
       
insert #t
       
select convert(varchar(10),dateadd(day,number,@starttime),120)
       
from master..spt_values
       
where type='P' and number between 0 and datediff(day,@starttime,@endtime)

       
set @sql=@sql+'isnull((select top 1 Balance from TZ_Money where convert(varchar(10),[Time],120)<=a.d and Balance is not null  order by time desc),0.00) 余额,a.d as [time]'
       
set @sql=@sql+' from #t a left join TZ_Money t on a.d=convert(varchar(10),t.[Time],120)   '
   
end
   
   
set @w=''
   
if @starttime<>'' and @starttime  is not null
       
set @w=' and datediff(d,'''+convert(varchar(10),@starttime,120)+''',[Time])>=0 '
   
if @endtime<>'' and @starttime  is not null
       
set @w=@w+' and datediff(d,'''+convert(varchar(10),@endtime,120)+''',[Time])<=0 '
   
if @uid<>'' and @uid  is not null
       
set @w=@w+' Uid='''+@uid+''''
   

   
set @g=' group by a.d'   

   
exec(@sql+@w+@g)
end
go

p_test1
'2010-5-01','2010-9-12','',''
go
p_test1
'2010-5-01','2010-9-12','',''
go
p_test1
'2010-5-01','2010-9-12','',''

/*

(所影响的行数为 3 行)


(所影响的行数为 1 行)

收入                                       支出                                       余额           time      
---------------------------------------- ---------------------------------------- ------------ ----------
8.00                                     59.00                                    49.00        2010

(所影响的行数为 1 行)


(所影响的行数为 5 行)

收入                                       支出                                       余额           time      
---------------------------------------- ---------------------------------------- ------------ ----------
.00                                      .00                                      .00          2010-05
4.00                                     9.00                                     95.00        2010-06
.00                                      .00                                      95.00        2010-07
4.00                                     50.00                                    49.00        2010-08
.00                                      .00                                      49.00        2010-09

(所影响的行数为 5 行)

警告: 聚合或其他 SET 操作消除了空值。

(所影响的行数为 135 行)

收入                                       支出                                       余额           time      
---------------------------------------- ---------------------------------------- ------------ ----------
.00                                      .00                                      .00          2010-05-01
.00                                      .00                                      .00          2010-05-02
.00                                      .00                                      .00          2010-05-03
.00                                      .00                                      .00          2010-05-04

......
.00                                      .00                                      .00          2010-05-28
.00                                      .00                                      .00          2010-05-29
.00                                      .00                                      .00          2010-05-30
.00                                      .00                                      .00          2010-05-31
.00                                      .00                                      .00          2010-06-01
.00                                      .00                                      .00          2010-06-02
.00                                      .00                                      .00          2010-06-03
.00                                      .00                                      .00          2010-06-04
.00                                      .00                                      .00          2010-06-05
.00                                      .00                                      .00          2010-06-06
4.00                                     9.00                                     95.00        2010-06-07
.00                                      .00                                      95.00        2010-06-08
.00                                      .00                                      95.00        2010-06-09
.00                                      .00                                      95.00        2010-06-10
.00                                      .00                                      95.00        2010-06-11
.00                                      .00                                      95.00        2010-06-12
.00                                      .00                                      95.00        2010-06-13
.00                                      .00                                      95.00        2010-06-14
.00                                      .00                                      95.00        2010-06-15
.00                                      .00                                      95.00        2010-06-16
.00                                      .00                                      95.00        2010-06-17
.00                                      .00                                      95.00        2010-06-18
.00                                      .00                                      95.00        2010-06-19
.00                                      .00                                      95.00        2010-06-20
.00                                      .00                                      95.00        2010-06-21
.00                                      .00                                      95.00        2010-06-22
.00                                      .00                                      95.00        2010-06-23
.00                                      .00                                      95.00        2010-06-24
.......

.00                                      .00                                      95.00        2010-08-01
.00                                      .00                                      95.00        2010-08-02
.00                                      .00                                      95.00        2010-08-03
.00                                      .00                                      95.00        2010-08-04
.00                                      .00                                      95.00        2010-08-05
.00                                      .00                                      95.00        2010-08-06
4.00                                     50.00                                    49.00        2010-08-07
.00                                      .00                                      49.00        2010-08-08
.00                                      .00                                      49.00        2010-08-09
.00                                      .00                                      49.00        2010-08-10
.....

.00                                      .00                                      49.00        2010-09-06
.00                                      .00                                      49.00        2010-09-07
.00                                      .00                                      49.00        2010-09-08
.00                                      .00                                      49.00        2010-09-09
.00                                      .00                                      49.00        2010-09-10
.00                                      .00                                      49.00        2010-09-11
.00                                      .00                                      49.00        2010-09-12

(所影响的行数为 135 行)

警告: 聚合或其他 SET 操作消除了空值。

<think>好的,我现在需要帮助用户解决在SQL Server中生成指定时间范围内所有日期的问题。首先,我得回顾用户提供的引用内容,看看有哪些现有的解决方案可以参考。用户提到了几个引用,其中引用2和引用3提到了生成日期范围的方法,特别是引用2中的用户定义函数GetDateRange,看起来这是一个可行的方案。用户可能希望得到一个可以直接使用的SQL脚本,生成从开始日期到结束日期的每一天日期。接下来,我需要考虑用户的实际需求。用户可能需要在查询或存储过程中动态生成这些日期,而不仅仅是静态列出。引用2中的函数使用了master..spt_values系统表,这是一个常见的做法,但需要注意权限和系统表的可用性。另外,引用4提到了生成随机日期,但用户的问题是关于生成所有日期,所以重点应放在引用2和引用3上。 另一个需要考虑的点是用户是否希望避免创建函数,而使用临时查询。有些用户可能没有权限创建函数,因此提供一个基于CTE或递归CTE的方法会更有帮助。例如,使用递归公用表表达式来生成日期序列,这可能更灵活,不需要依赖系统表。 此外,用户可能关心如何处理不同的日期范围,包括开始和结束日期的包含性。确保生成的日期包括开始和结束日期之间的所有天数。在编写SQL时,DATEDIFF函数和DATEADD函数的正确使用是关键。还需要验证提供的脚本是否正确,比如在引用2的函数中,是否确实能生成所有日期。检查其中的BETWEEN0ANDDATEDIFF(DAY,@BeginDate,@EndDate),这里DATEDIFF返回的是两个日期之间的天数差,加上0到该差值,可以确保包括开始和结束日期。例如,如果开始和结束是同一天,DATEDIFF返回0,那么number BETWEEN0AND0,会生成那一天。 另外,用户可能需要一个更简洁的方法,比如使用CTE递归生成日期,而不需要创建函数。这可能更适合一次性使用的情况。递归CTE的写法需要确保终止条件正确,避免无限递归。 最后,总结几种方法:创建用户定义函数、使用递归CTE、使用系统表spt_values。需要比较它们的优缺点,帮助用户选择最适合的方式。同时,提醒用户注意日期格式和时区问题,确保生成的日期符合预期。</think>在SQL Server中生成指定时间范围内的所有日期,可以通过以下三种方法实现: ### 方法一:使用系统表+数字序列(推荐) ```sql DECLARE @BeginDate DATE = '2023-01-01' DECLARE @EndDate DATE = '2023-01-07' SELECT DATEADD(DAY, number, @BeginDate) AS DateItem FROM master..spt_values WHERE type = 'P' AND number BETWEEN 0 AND DATEDIFF(DAY, @BeginDate, @EndDate) ``` 原理:利用系统表`spt_values`中的连续数字序列,通过`DATEADD`函数生成日期范围[^2] ### 方法二:递归CTE生成 ```sql DECLARE @Start DATE = '2023-01-01' DECLARE @End DATE = '2023-01-07' ;WITH DateCTE AS ( SELECT @Start AS DateItem UNION ALL SELECT DATEADD(DAY, 1, DateItem) FROM DateCTE WHERE DateItem < @End ) SELECT * FROM DateCTE OPTION (MAXRECURSION 0) ``` 特点:无需依赖系统表,通过递归生成日期序列,适合大范围日期生成[^3] ### 方法三:创建日期生成函数 ```sql CREATE FUNCTION dbo.GetDateRange ( @BeginDate DATE, @EndDate DATE ) RETURNS TABLE AS RETURN ( SELECT TOP (DATEDIFF(DAY, @BeginDate, @EndDate) + 1) DateItem = DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) -1, @BeginDate) FROM sys.objects a CROSS JOIN sys.objects b ) ``` 用法:`SELECT * FROM dbo.GetDateRange('2023-01-01','2023-01-07')`[^2]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值