我试图弄清楚如何编写一个查询,该查询将返回一个包含 61 条记录的表,该表将列出当前日期的每条记录的日期。
5 回答
在 SQL-Server 中获取 61 个日期列表的最简单且可能最有效的方法是使用系统表 Master.dbo.spt_values:
SELECT [Date] = DATEADD(DAY, number - 30, CAST(CURRENT_TIMESTAMP AS DATE))
FROM Master..spt_values
WHERE Type = 'P'
AND Number <= 60;
编辑
如果您担心使用未记录的系统表,那么这将做同样的事情(同样没有循环)
WITH T AS
( SELECT Number = ROW_NUMBER() OVER(ORDER BY Object_ID)
FROM sys.all_objects
)
SELECT [Date] = DATEADD(DAY, number - 30, CAST(CURRENT_TIMESTAMP AS DATE))
FROM T
WHERE Number <= 60;
这里已经对生成数字序列的各种方法的优点进行了广泛的测试。我的首选选项始终是您自己的表格(例如 dbo.numbers,或者在本例中为日历表格)。
这是我使用的一个有用的功能,取自这里:
只需发送 Date-30 和 Date+30
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
);
GO
如果您不想要该功能,也可以简单地将其用作查询,声明
@startdate = @myDate - 30
和
@enddate = @myDate + 30
尝试这个
;with DateList As
(
select GETDATE() as DateCol
union all
select datecol + 1 from datelist
where DateDiff(d, getdate(),datecol+1) < 31 and DateCol + 1 > GETDATE()
union all
select datecol - 1 from datelist
where DateDiff(d, datecol-1, getdate()) < 31 and DateCol - 1 < GETDATE()
)
select CONVERT(varchar(15), DateCol, 101) DateCol from DateList
order by 1
OPTION (MAXRECURSION 0)
如果你想加入其他表
declare @t table (code varchar(10));
insert into @t
values ('a'), ('b')
;with DateList As
(
select GETDATE() as DateCol
union all
select datecol + 1 from datelist
where DateDiff(d, getdate(),datecol+1) < 31 and DateCol + 1 > GETDATE()
union all
select datecol - 1 from datelist
where DateDiff(d, datecol-1, getdate()) < 31 and DateCol - 1 < GETDATE()
)
select * from DateList, @t
OPTION (MAXRECURSION 0)
在我看来,解决这个问题的最佳方法不是使用递归 ctes、临时表或系统表,而是创建和重用日期查找表。创建一次查找表,然后您可以根据需要使用它。
从那里,很容易生成日期列表:
select *
from datelookup
where datefull >= dateadd(day,-30,convert(varchar(10), getDate(), 120))
and datefull <= dateadd(day,30,convert(varchar(10), getDate(), 120));
SQL Fiddle Demo(包括创建此类表的示例代码)
This T-SQL code will generate your table:
DECLARE @dates TABLE (date_item DATE)
DECLARE @day DATE = DATEADD(DAY, -30, N'2013-05-02')
WHILE @day <= DATEADD(DAY, 30, N'2013-05-02')
BEGIN
INSERT INTO @dates (date_item) SELECT @day
SET @day = DATEADD(DAY, 1, @day)
END
The result is in @dates
. Obviously you will need to set the desired value for the center date in place of N'2013-05-02'