views:

1562

answers:

7

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

A: 

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
Eppz
This only works if there is a date in the table for each year. If there are no entries for 2006, say, then 2006 will not appear.
Jonathan Leffler
@Jonathan, This code is independent of a table. This code prints "a list of years as a recordset starting with 2004 to current year (in desc order), without writing a stored procedure". While I believe that printing the values was the wrong choice, my solution does the same an returns the result set
scottm
This would work, but I like Lievens answer above as it is one select statement and uses some SQL 2005 stuff I needed to learn :-)
Graeme
A: 

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.

Andrew Clark
How do you propose keeping this dates table up-to-date? Is your application going to crash on January 1 several years down the road because someone forgot to populate it with next year's dates?
bcwood
+2  A: 

Replace AnyTable with a table with at least the amount of rows as the amount of years you're asking. Replace AnyColumn with a column from the table.

SELECT *
FROM (
  SELECT TOP 100 2003 + ROW_NUMBER() OVER (ORDER BY <AnyColumn>) AS Yr
  FROM dbo.<AnyTable>
  ) Years
WHERE Yr <= YEAR(GETDATE())
Lieven
That works - presumably I should choose a table with only a handful of rows, or does it make no difference?
Graeme
@Graeme, by doing a TOP 100 it will make little difference wich table you choose but I'd use a small one.
Lieven
You have to create a table, add the current year - 2004 number of rows, then run this query? What happens next year?
scottm
@scotty2012. No table gets created. Next year gets included by the YEAR(GETDATE()) statement. The only thing fixed is the starting year. There are no 2004 rows, only 100 as specified in the TOP 100 clause. This query will work up until 2103
Lieven
What happens when the table you're selecting from only has 2 rows in it?
Eppz
Only two years will be returned.
Lieven
So if only 2 rows would be returned, then this would not give the expected results.
Eppz
@Eppz, I explained in my response that AnyTable should be replaced with a table with "at least" the amount of rows as the amount of years you're asking.
Lieven
You need to add ORDER BY 1 desc to get the years in the correct order.
Eppz
@Eppz. True, I left that as an excercise to the reader ;) (read as: I honestly forgot).
Lieven
+3  A: 

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
DJ
Nathan Koop
heh - missed the current year comment but the performance impact of something this small would be negligible
DJ
@DJ sorry, I totally misread the intended query, I for some reason thought this was going to be joined with an order table or something. My mistake. Your query is perfectly fine.
Nathan Koop
A: 
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
Max Gontar
A: 

Any particular reason a table-valued UDF is unacceptable? Do something like this otherwise.

Pontus Gagge
I am not allowed to create database objects, so only select statement alowed.
Graeme
A: 
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
scottm