如何创建查询以获取 SQL 中的先前日期?

How to create a query to get previous dates in SQL?

我有一个日期并试图获取前 5 个月的结束日期,如下所示:

DECLARE @date Date =  '2020-04-30'

SELECT DATEADD(MONTH, DATEDIFF(MONTH, -1, @date)-1, -1)
SELECT DATEADD(MONTH, DATEDIFF(MONTH, -2, @date)-1, -1)
---
SELECT DATEADD(MONTH, DATEDIFF(MONTH, -5, @date)-1, -1)

如果我们在变量中传递之前的月份数,是否有办法在单个查询中获取所有之前的日期,在上述情况下它在 SQL Server 2008 中为 5?

也许你是这个意思?

DECLARE @date date =  '2020-04-30';

SELECT EOMONTH(@date, T.I)
FROM (VALUES(-1),(-2),(-3),(-4),(-5))T(I)
ORDER BY T.I DESC;

如果您想要更大的范围,则可以即时创建计数:

DECLARE @date date =  '2020-04-30',
        @Months int = 500; --

WITH N AS(
    SELECT N
    FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
    SELECT TOP (@Months) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
    FROM N N1,  N N2, N N3, N N4)
SELECT EOMONTH(@Date, T.I * -1)
FROM Tally T;

OP 似乎使用了不受支持的 SQL 服务器版本,因此没有告诉我们这一点。他们可以在 SQL Server 2008 中使用以下内容(我不记得它在 2005 中是否有效):

DECLARE @date date =  '2020-04-30';

SELECT DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH,0,@date)+T.I,0))
FROM (VALUES(0),(-1),(-2),(-3),(-4))T(I)
ORDER BY T.I DESC;

对于更大的范围,这将在 2008 年工作,但 将不会 在 2005 年或之前工作。但是,如果您使用的是这些版本中的任何一个,那么您完成升级的时间就过去了(特别是对于 SQL Server 2005):

DECLARE @date date =  '2020-04-30',
        @Months int = 500;

WITH N AS(
    SELECT N
    FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
    SELECT TOP (@Months) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 AS I
    FROM N N1,  N N2, N N3, N N4)
SELECT DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH,0,@date)-T.I,0))
FROM Tally T;

使用EOMONTH()获取月末日期

DECLARE @date Date =  '2020-04-30'
SELECT  EOMONTH(DATEADD(MONTH, -1, @date)),
        EOMONTH(DATEADD(MONTH, -2, @date)),
        EOMONTH(DATEADD(MONTH, -3, @date)),
        EOMONTH(DATEADD(MONTH, -4, @date)),
        EOMONTH(DATEADD(MONTH, -5, @date))

您想要按列还是按行?

SELECT  EOMONTH(DATEADD(MONTH, -1, @date)) UNION ALL
SELECT  EOMONTH(DATEADD(MONTH, -2, @date)) UNION ALL
SELECT  EOMONTH(DATEADD(MONTH, -3, @date)) UNION ALL
SELECT  EOMONTH(DATEADD(MONTH, -4, @date)) UNION ALL
SELECT  EOMONTH(DATEADD(MONTH, -5, @date))

对于 SQL Server 2008,您可以使用参数并生成前几个月的最后一天,如下所示。

-- OLD Version
DECLARE @dt DATE
SET @dt = GETDATE()
DECLARE @n INT = 3 --number of previous months
;WITH CTE_previousMonths AS
(
SELECT CAST(DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,@dt),0)) AS DATE)as LastDayOfMonth, 1 AS lvl
UNION ALL
SELECT CAST(DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,LastDayOfMonth),0)) AS DATE)as LastDayOfMonth, lvl+1 AS lvl
FROM CTE_previousMonths WHERE lvl < @n
)
SELECT * FROM CTE_previousMonths
+----------------+-----+
| LastDayOfMonth | lvl |
+----------------+-----+
| 2020-04-30     |   1 |
| 2020-03-31     |   2 |
| 2020-02-29     |   3 |
+----------------+-----+
DECLARE @MonthsBack int     =   5                           -- Amount of Months you want to go back
DECLARE @TargetDate date    =  '2020-04-30'                 -- Date where we start to go back

WHILE   @MonthsBack > 0                                     -- Loop until no more months to go back
    BEGIN                                   
        SELECT  DATEADD(MONTH, -1*@MonthsBack, @TargetDate) --  Function to add any datepart to a date.
                                                            --  If the number of parts is negative, it will substarct instead.
                                                            --  In our case we want to add Months, so we pick that interval.
                                                            --  Since we really want to substract (go back), we multiply the amount of months by -1
        SET @MonthsBack = @MonthsBack - 1                   --  Now, decrease the loop variable, same we use to substract months.
    END
;