Reputation: 2667
I need a list of years as a recordset starting with 2004 to current year (in desc order), without writing a stored procedure. Is this possible? (SQL Server 2005). So it should return:
2009
2008
2007
2006
2005
2004
Upvotes: 33
Views: 73424
Reputation: 244
Recursive CTE with no variables is a simpler way to go...
WITH Years AS (
SELECT DATEPART(YEAR, GETDATE()) AS Year
UNION ALL
Select Year - 1 FROM Years
WHERE Year > 2004
)
SELECT Year FROM Years
ORDER BY Year DESC
Upvotes: 0
Reputation: 191
My two cents:
The CTE is the best answer but I like @Lieven Keersmaekers answer as it doesn’t rely on recursion/loops or creating additional objects such as functions/date-tables. The key variation is mine simply uses the Top clause with an expression, instead of the top 100 (basically the whole table) I ask for N number of unordered rows first. This is quicker, if your base table happens to be quite large.
Tested on SQL Server 2016
DECLARE @startYear smallint;
SET @startYear = 2004;
DECLARE @endYear smallint;
SET @endYear = YEAR(GETDATE());
-- Top uses expression to bring in N number of rows. The (@startYear - 1) is to retain the start year
SELECT [Yr]
FROM (
SELECT TOP (@endYear - (@startYear - 1))
COUNT([object_id]) OVER (ORDER BY [object_id] DESC) + (@startYear - 1) AS [Yr] -- Add initial start year to Count
FROM sys.all_objects
) AS T1
ORDER BY [Yr] DESC
The comments above are valid, but Since OP’s requirements is literally a small set of values from 2004, the sys.all_objects will suffice, as SQL Server install comes with a ton of system objects.
Hope that's a different take.
Upvotes: 1
Reputation: 21
WITH n(n) AS
(
SELECT 0
UNION ALL
SELECT n+1 FROM n WHERE n < 10
)
SELECT year(DATEADD( YY, -n, GetDate()))
FROM n ORDER BY n
Upvotes: 2
Reputation: 1
This is a simple query, check this
(SELECT REPLACE((TO_CHAR(SYSDATE,'YYYY')-Rownum)+1,' ',NULL) yr FROM dual CONNECT BY LEVEL < 32) year
Upvotes: 0
Reputation: 58491
Using ROW_NUMBER
on any column from any large enough (stable) table would be one way to do it.
SELECT *
FROM (
SELECT TOP 100 2003 + ROW_NUMBER() OVER (ORDER BY <AnyColumn>) AS Yr
FROM dbo.<AnyTable>
) Years
WHERE Yr <= YEAR(GETDATE())
Note that <AnyTable>
should contain at least the amount of rows equal to the amount of years you require.
system table
should come to mind.CTE
like mentioned in the answer given by Joshua. The CTE
technique is far superior and less error prone than current given ROW_NUMBER
solution.Upvotes: 5
Reputation: 13740
This gets all years from 2004 to the present, using a recursive CTE:
with yearlist as
(
select 2004 as year
union all
select yl.year + 1 as year
from yearlist yl
where yl.year + 1 <= YEAR(GetDate())
)
select year from yearlist order by year desc;
Upvotes: 61
Reputation: 3226
Try this:
declare @lowyear int
set @lowyear = 2004
declare @thisyear int
set @thisyear = year(getdate())
while @thisyear >= @lowyear
begin
print @thisyear
set @thisyear = (@thisyear - 1)
end
Returns
2009
2008
2007
2006
2005
2004
When you hit Jan 1, 2010. The same code will return:
2010
2009
2008
2007
2006
2005
2004
Upvotes: 2
Reputation: 16257
Updated to return current year plus previous 5 years. Should be very fast as this is a small recordset.
SELECT YEAR(GETDATE()) as YearNum
UNION
SELECT YEAR(GETDATE()) - 1 as YearNum
UNION
SELECT YEAR(GETDATE()) - 2 as YearNum
UNION
SELECT YEAR(GETDATE()) - 3 as YearNum
UNION
SELECT YEAR(GETDATE()) - 4 as YearNum
UNION
SELECT YEAR(GETDATE()) - 5 as YearNum
ORDER BY YearNum DESC
Upvotes: 6
Reputation: 28699
SET NOCOUNT ON
DECLARE @max int
set @max = DATEPART(year, getdate())
CREATE TABLE #temp (val int)
while @max >= 2004
BEGIN
insert #temp(val) values(@max)
set @max = @max - 1
END
SELECT * from #temp
Upvotes: 0
Reputation: 22775
DECLARE @YEARS TABLE (Y INT)
DECLARE @I INT, @NY INT
SELECT @I = 2004, @NY = YEAR(GETDATE())
WHILE @I <= @NY BEGIN
INSERT @YEARS SELECT @I
SET @I = @I + 1
END
SELECT Y
FROM @YEARS
ORDER BY Y DESC
Upvotes: 3
Reputation: 1403
I think you need to create a dates table, then just select your range from it. It can also come in useful when you need to select a date range with X data attached and not have any missed days.
Upvotes: 0