我的问题类似于这个 MySQL问题,但是用于SQL Server:
是否有函数或查询将返回两个日期之间的天数列表?例如,假设有一个名为ExplodeDates的函数:
SELECT ExplodeDates('2010-01-01', '2010-01-13');
Run Code Online (Sandbox Code Playgroud)
这将返回一个包含以下值的列表:
2010-01-01
2010-01-02
2010-01-03
2010-01-04
2010-01-05
2010-01-06
2010-01-07
2010-01-08
2010-01-09
2010-01-10
2010-01-11
2010-01-12
2010-01-13
Run Code Online (Sandbox Code Playgroud)
我认为日历/数字表可能能够帮助我.
更新
我决定查看提供的三个代码答案,执行结果 - 占总批次的百分比 - 是:
越低越好
我已经接受了Rob Farley的答案,因为它是最快的,尽管数字表解决方案(KM和StingyJack在他们的答案中使用)都是我的最爱.Rob Farley的速度提高了三分之二.
更新2
阿丽维亚的答案更为简洁.我已经改变了接受的答案.
小智 101
这几行是sql server中这个问题的简单答案.
WITH mycte AS
(
SELECT CAST('2011-01-01' AS DATETIME) DateValue
UNION ALL
SELECT DateValue + 1
FROM mycte
WHERE DateValue + 1 < '2021-12-31'
)
SELECT DateValue
FROM mycte
OPTION (MAXRECURSION 0)
Run Code Online (Sandbox Code Playgroud)
Rob*_*ley 67
尝试这样的事情:
CREATE FUNCTION dbo.ExplodeDates(@startdate datetime, @enddate datetime)
returns table as
return (
with
N0 as (SELECT 1 as n UNION ALL SELECT 1)
,N1 as (SELECT 1 as n FROM N0 t1, N0 t2)
,N2 as (SELECT 1 as n FROM N1 t1, N1 t2)
,N3 as (SELECT 1 as n FROM N2 t1, N2 t2)
,N4 as (SELECT 1 as n FROM N3 t1, N3 t2)
,N5 as (SELECT 1 as n FROM N4 t1, N4 t2)
,N6 as (SELECT 1 as n FROM N5 t1, N5 t2)
,nums as (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) as num FROM N6)
SELECT DATEADD(day,num-1,@startdate) as thedate
FROM nums
WHERE num <= DATEDIFF(day,@startdate,@enddate) + 1
);
Run Code Online (Sandbox Code Playgroud)
然后你使用:
SELECT *
FROM dbo.ExplodeDates('20090401','20090531') as d;
Run Code Online (Sandbox Code Playgroud)
编辑(接受后):
请注意......如果您已经有足够大的nums表,那么您应该使用:
CREATE FUNCTION dbo.ExplodeDates(@startdate datetime, @enddate datetime)
returns table as
return (
SELECT DATEADD(day,num-1,@startdate) as thedate
FROM nums
WHERE num <= DATEDIFF(day,@startdate,@enddate) + 1
);
Run Code Online (Sandbox Code Playgroud)
您可以使用以下方法创建这样的表:
CREATE TABLE dbo.nums (num int PRIMARY KEY);
INSERT dbo.nums values (1);
GO
INSERT dbo.nums SELECT num + (SELECT COUNT(*) FROM nums) FROM nums
GO 20
Run Code Online (Sandbox Code Playgroud)
这些行将创建一个包含1M行的数字表...并且比逐个插入它们要快得多.
您不应该使用涉及BEGIN和END的函数创建ExplodeDates函数,因为查询优化器根本无法简化查询.
小智 17
这完全是你想要的,修改自Will的早期帖子.不需要辅助表或循环.
WITH date_range (calc_date) AS (
SELECT DATEADD(DAY, DATEDIFF(DAY, 0, '2010-01-13') - DATEDIFF(DAY, '2010-01-01', '2010-01-13'), 0)
UNION ALL SELECT DATEADD(DAY, 1, calc_date)
FROM date_range
WHERE DATEADD(DAY, 1, calc_date) <= '2010-01-13')
SELECT calc_date
FROM date_range;
Run Code Online (Sandbox Code Playgroud)
小智 6
DECLARE @MinDate DATETIME = '2012-09-23 00:02:00.000',
@MaxDate DATETIME = '2012-09-25 00:00:00.000';
SELECT TOP (DATEDIFF(DAY, @MinDate, @MaxDate) + 1) Dates = DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, @MinDate)
FROM sys.all_objects a CROSS JOIN sys.all_objects b;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
145872 次 |
| 最近记录: |