Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return temp table of continuous dates

I need to create a function that returns a table of continuous dates. I would pass in a min & max date.

I expect it to be able to be called like this:

SELECT * FROM GetDates('01/01/2009', '12/31/2009')

I currently have a stored proc that does this, but requirements changed and now I need to do include the returned data from within a union:

 with mycte as
(
     select cast(@minDate as datetime) DateValue
     union all
     select DateValue + 1
     from    mycte   
     where   DateValue + 1 <= @maxDate
 )
 select DateValue
 from    mycte
option (maxrecursion 1000)

The problem, however, is that I need to set the recursion to be greater than 100. According to a post by Gail Erickson [MS] on eggheadcafe, this is not currently supported.

Without creating a real (not temporary) table with just date in it, is there a way to do this?

I am using SqlServer2005.

like image 385
Nathan Koop Avatar asked Sep 08 '09 17:09

Nathan Koop


People also ask

What is #temp in SQL?

A temporary table is a base table that is not stored in the database but instead exists only while the database session in which it was created is active.

Is CTE a temp table?

CTE stands for Common Table Expressions. It was introduced with SQL Server 2005. It is a temporary result set and typically it may be a result of complex sub-query. Unlike the temporary table, its life is limited to the current query.

How do I create a global temporary table in SQL?

A global temporary table is created using CREATE TABLE statement with the table name prefixed with a double number sign (##table_name). In SQL Server, global temporary tables are visible to all sessions (connections). So if you create a global temporary table in one session, you can start using it in other sessions.

How do I drop a global temporary table in SQL Server?

After creation, global temporary tables become visible to any user and any connection. They can be manually dropped with DROP TABLE command. Global temporary tables are automatically dropped when the session that create the table completes and there is no active references to that table.


2 Answers

Your best option is to actually have a physical table of dates. There aren't that many for even long periods, and will be much faster than materializing them on-the-fly from temp tables or recursive ctes.

like image 183
Remus Rusanu Avatar answered Sep 23 '22 17:09

Remus Rusanu


If you choose to (or need to) go with an ad-hoc table and not a permanent one, this would do it:

CREATE FUNCTION dbo.DateList
 (
   @MinDate datetime
  ,@MaxDate datetime
 )
RETURNS TABLE
RETURN WITH
  Pass0 as (select 1 as C union all select 1), --2 rows
  Pass1 as (select 1 as C from Pass0 as A, Pass0 as B),--4 rows
  Pass2 as (select 1 as C from Pass1 as A, Pass1 as B),--16 rows
  Pass3 as (select 1 as C from Pass2 as A, Pass2 as B),--256 rows
  Pass4 as (select 1 as C from Pass3 as A, Pass3 as B),--65536 rows
  Tally as (select row_number() over(order by C) as Number from Pass4)
 select dateadd(dd, Number - 1, @MinDate) DateValue
 from Tally
 where Number < datediff(dd, @MindAte, @MaxDate) + 2

GO

And a testing call:

DECLARE
  @MinDate datetime
 ,@MaxDate datetime

SET @MinDate = 'Jan 1, 2009'
SET @MaxDate = 'Dec 31, 2009'

SELECT *
 from dbo.DateList(@MinDate, @MaxDate)

Wierd--this is the third SO post today that involved Tally tables. Must be some odd sunspot activity going on. Here are the linkes:

count number of rows that occur for each date in column date range.
What is the best way to create and populate a numbers table?

like image 22
Philip Kelley Avatar answered Sep 26 '22 17:09

Philip Kelley