SQL 服务器 - 有效生成范围内的日期
SQL Server - Efficient generation of dates in a range
使用 SQL 服务器 2016。
我有一个存储过程,它生成一个日期范围内的选项列表。为了清楚起见,针对天数的运输选项,但对此处的具体细节并不重要。
存储过程的第一步生成一个日期列表来存储额外的数据,生成这个列表所花费的时间比代码的平衡时间要长得多。虽然这个过程个别很短,但调用的次数意味着这段代码使系统承受的负载比其他任何代码都大。
考虑到这一点,我一直在测试几个选项的效率。
迭代常用table表达式:
CREATE FUNCTION [dbo].[udf_DateRange_CTE] (@StartDate DATE,@EndDate DATE)
RETURNS @Return TABLE (Date DATE NOT NULL)
AS
BEGIN
WITH dates(date)
AS (SELECT @StartDate [Date]
UNION ALL
SELECT DATEADD(dd, 1, [Date])
FROM dates
WHERE [Date] < @EndDate
)
INSERT INTO @Return
SELECT date
FROM dates
OPTION (MAXRECURSION 0)
RETURN
END
一个 while 循环:
CREATE FUNCTION [dbo].[udf_DateRange_While] (@StartDate DATE,@EndDate DATE)
RETURNS @Retun TABLE (Date DATE NOT NULL,PRIMARY KEY (Date))
AS
BEGIN
WHILE @StartDate <= @EndDate
BEGIN
INSERT INTO @Retun
VALUES (@StartDate)
SET @StartDate = DATEADD(DAY,1,@StartDate)
END
RETURN
END
从预填充的 table 日期中查找:
CREATE FUNCTION [dbo].[udf_DateRange_query] (@StartDate DATE,@EndDate DATE)
RETURNS @Return TABLE (Date DATE NOT NULL)
AS
BEGIN
INSERT INTO @Return
SELECT Date
FROM DateLookup
WHERE Date >= @StartDate
AND Date <= @EndDate
RETURN
END
在效率方面,我测试了生成一年的日期,1000 次并得到以下结果:
- CTE:10.0 秒
- 同时:7.7 秒
- 查询:2.6 秒
由此看来,查询绝对是更快的选择,但确实需要永久 table 需要创建和维护的日期。这意味着该查询并不孤单 "self-contained" 并且可以请求给定日期范围之外的日期。
有谁知道生成范围日期的任何更有效的方法,或者我可以对上述内容应用的任何优化?
非常感谢。
您可以像下面这样尝试。与 CTE
或 WHILE
循环相比,这应该是快速的。
DECLARE @StartDate DATETIME = Getdate() - 1000
DECLARE @EndTime DATETIME = Getdate()
SELECT *
FROM (SELECT @StartDate + RN AS DATE
FROM (SELECT ROW_NUMBER()
OVER (
ORDER BY (SELECT NULL)) RN
FROM master..[spt_values]) T) T1
WHERE T1.DATE <= @EndTime
ORDER BY DATE
注意:这适用于日差 <= 2537 天
如果您想支持更多范围,您可以在 master..[spt_values]
上使用 CROSS JOIN
来生成 0 - 6436369 天之间的范围,如下所示。
DECLARE @StartDate DATETIME = Getdate() - 10000
DECLARE @EndTime DATETIME = Getdate()
SELECT @StartDate + RN AS DATE FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) RN
FROM master..[spt_values] T1
CROSS JOIN master..[spt_values] T2
) T
WHERE RN <= DATEDIFF(DAY,@StartDate,@EndTime)
使用 SQL 服务器 2016。
我有一个存储过程,它生成一个日期范围内的选项列表。为了清楚起见,针对天数的运输选项,但对此处的具体细节并不重要。
存储过程的第一步生成一个日期列表来存储额外的数据,生成这个列表所花费的时间比代码的平衡时间要长得多。虽然这个过程个别很短,但调用的次数意味着这段代码使系统承受的负载比其他任何代码都大。
考虑到这一点,我一直在测试几个选项的效率。
迭代常用table表达式:
CREATE FUNCTION [dbo].[udf_DateRange_CTE] (@StartDate DATE,@EndDate DATE)
RETURNS @Return TABLE (Date DATE NOT NULL)
AS
BEGIN
WITH dates(date)
AS (SELECT @StartDate [Date]
UNION ALL
SELECT DATEADD(dd, 1, [Date])
FROM dates
WHERE [Date] < @EndDate
)
INSERT INTO @Return
SELECT date
FROM dates
OPTION (MAXRECURSION 0)
RETURN
END
一个 while 循环:
CREATE FUNCTION [dbo].[udf_DateRange_While] (@StartDate DATE,@EndDate DATE)
RETURNS @Retun TABLE (Date DATE NOT NULL,PRIMARY KEY (Date))
AS
BEGIN
WHILE @StartDate <= @EndDate
BEGIN
INSERT INTO @Retun
VALUES (@StartDate)
SET @StartDate = DATEADD(DAY,1,@StartDate)
END
RETURN
END
从预填充的 table 日期中查找:
CREATE FUNCTION [dbo].[udf_DateRange_query] (@StartDate DATE,@EndDate DATE)
RETURNS @Return TABLE (Date DATE NOT NULL)
AS
BEGIN
INSERT INTO @Return
SELECT Date
FROM DateLookup
WHERE Date >= @StartDate
AND Date <= @EndDate
RETURN
END
在效率方面,我测试了生成一年的日期,1000 次并得到以下结果:
- CTE:10.0 秒
- 同时:7.7 秒
- 查询:2.6 秒
由此看来,查询绝对是更快的选择,但确实需要永久 table 需要创建和维护的日期。这意味着该查询并不孤单 "self-contained" 并且可以请求给定日期范围之外的日期。
有谁知道生成范围日期的任何更有效的方法,或者我可以对上述内容应用的任何优化?
非常感谢。
您可以像下面这样尝试。与 CTE
或 WHILE
循环相比,这应该是快速的。
DECLARE @StartDate DATETIME = Getdate() - 1000
DECLARE @EndTime DATETIME = Getdate()
SELECT *
FROM (SELECT @StartDate + RN AS DATE
FROM (SELECT ROW_NUMBER()
OVER (
ORDER BY (SELECT NULL)) RN
FROM master..[spt_values]) T) T1
WHERE T1.DATE <= @EndTime
ORDER BY DATE
注意:这适用于日差 <= 2537 天
如果您想支持更多范围,您可以在 master..[spt_values]
上使用 CROSS JOIN
来生成 0 - 6436369 天之间的范围,如下所示。
DECLARE @StartDate DATETIME = Getdate() - 10000
DECLARE @EndTime DATETIME = Getdate()
SELECT @StartDate + RN AS DATE FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) RN
FROM master..[spt_values] T1
CROSS JOIN master..[spt_values] T2
) T
WHERE RN <= DATEDIFF(DAY,@StartDate,@EndTime)