admin管理员组文章数量:1421943
If I was to do a simple select statement that returned one row, where the first column is a row number - in this instance a 1, a start date and an end date. .
SELECT 1, GETDATE(), DATEADD(year,1,GETDATE()) 'EffectiveToDate'
So this would give me 1, 2025-01-17 and one year later 2026-01-16.
What I want to achieve, is a further 9 rows - 2 through to 10 that would then be the same as row one - but one year one.
So Row 2 would be -
2, 2026-01-17 and 2027-01-16
and so on. . .
If I was to do a simple select statement that returned one row, where the first column is a row number - in this instance a 1, a start date and an end date. .
SELECT 1, GETDATE(), DATEADD(year,1,GETDATE()) 'EffectiveToDate'
So this would give me 1, 2025-01-17 and one year later 2026-01-16.
What I want to achieve, is a further 9 rows - 2 through to 10 that would then be the same as row one - but one year one.
So Row 2 would be -
2, 2026-01-17 and 2027-01-16
and so on. . .
Share Improve this question edited Jan 19 at 20:17 Thom A 96.3k11 gold badges61 silver badges95 bronze badges asked Jan 17 at 15:44 ikilledbillikilledbill 2411 gold badge3 silver badges19 bronze badges 3 |2 Answers
Reset to default 1Managed to do it this way -
declare @startDate datetime,
@endDate datetime;
select @startDate = getdate(),
@endDate = dateadd(year,1,getdate()) -1
;with myCTE as
(
select 1 as ROWNO,@startDate "StartDate" ,@EndDate "EndDate"
union all
select ROWNO+1 ,dateadd(YEAR, 1, StartDate) , dateadd(YEAR, 1, EndDate)
FROM myCTE
where ROWNO+1 <= 10
)
select ROWNO,Convert(varchar(10),StartDate,105) as StartDate ,Convert(varchar(10),EndDate,105) from myCTE
There are many way you can achieve this. One of the simplest is likely using GENERATE_SERIES
:
SELECT GS.value+1,
DATEADD(YEAR, -GS.Value,GETDATE()) AS DateFrom,
DATEADD(YEAR, -GS.Value+1,GETDATE()) AS DateTo
FROM GENERATE_SERIES(0,9,1) GS;
If you aren't on SQL Server 2022+, then you won't have access to the function. For such a small number, you could just put the literal values in a VALUES
clause:
SELECT V.value+1,
DATEADD(YEAR,-V.Value, GETDATE()) AS DateFrom,
DATEADD(YEAR, -V.Value+1,GETDATE()) AS DateTo
FROM (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9))V(Value);
If you wanted this scale, however, you could use an inline tally:
DECLARE @I int = 10;
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
SELECT TOP (@I) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
FROM N N1, N N2, N N3, N N4, N N5, N N6, N N7) --Up to 10,000,000 rows
SELECT T.I,
DATEADD(YEAR,-T.I+1, GETDATE()) AS DateFrom,
DATEADD(YEAR, -T.I+2,GETDATE()) AS DateTo
FROM Tally T;
Or you could also create a UDF for the Tally and use that:
CREATE FUNCTION [fn].[Tally] (@LastNumber bigint, @Zero bit)
RETURNS table
WITH SCHEMABINDING
AS RETURN
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
SELECT 0 AS I
WHERE @Zero = 0
AND @LastNumber IS NOT NULL
UNION ALL
SELECT TOP (ISNULL(@LastNumber,0))
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
FROM N N1, N N2, N N3, N N4, N N5, N N6, N N7) --Up to 10,000,000 rows
SELECT I
FROM Tally T;
GO
SELECT T.I+1,
DATEADD(YEAR, -T.I+1,GETDATE()) AS DateFrom,
DATEADD(YEAR, -T.I+2,GETDATE()) AS DateTo
FROM fn.Tally(9,0) T;
Or, finally, you could use a Calendar table. One method could look like this, however, note this actually fails if the current date is 29 February:
SELECT ROW_NUMBER() OVER (ORDER BY C.CalendarDate DESC),
C.CalendarDate AS DateFrom,
DATEADD(YEAR, 1, C.CalendarDate) AS DateTo
FROM tbl.Calendar C
WHERE C.CalendarMonth = MONTH(GETDATE())
AND C.CalendarDay = DAY(GETDATE())
AND C.CalendarYear >= YEAR(GETDATE()) - 9
AND C.CalendarYear <= YEAR(GETDATE());
It would, in truth, likely be easier to use a Tally here, rather than a Calendar table.
本文标签: sql serverAutomate up to 10 years in a result setStack Overflow
版权声明:本文标题:sql server - Automate up to 10 years in a result set - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745357224a2655125.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
'
) for aliases. Single quotes are for literal strings, not delimit identifying object names. They have some "gotchas" as their behaviour is not consistent depending on where they are referenced. Also some syntaxes with literal string aliases are deprecated. Stick to object and alias names that don't need delimit identifying, and if you must delimit identify them use T-SQL's identifier, brackets ([]
), or ANSI-SQL's, double quotes ("
). – Thom A Commented Jan 17 at 16:07