2009-09-08 13 views
5

Devo creare una funzione che restituisca una tabella di date continue. Vorrei passare in un minuto massimo & data.Tabella temp di ritorno delle date continue

mi aspetto che sia in grado di essere chiamato in questo modo:

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

Al momento ho un proc memorizzato che fa questo, ma i requisiti cambiato e ora ho bisogno di fare includere i dati restituiti da all'interno di un'unione :

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) 

il problema, tuttavia, è che devo impostare la ricorsione per essere maggiore di 100. Secondo un post di Gail Erickson [MS] su eggheadcafe, questo non è attualmente supportato.

Senza creare un vero (non temporaneo) tabella con solo la data in esso, c'è un modo per farlo?

Sto usando SqlServer2005.

+0

E 'possibile avere livello ricorsione impostato ad un valore superiore a 100. Se ricordo correggere il livello massimo supportato è 2^15. – Faiz

risposta

6

tuo l'opzione migliore è avere effettivamente una tabella di date fisica. Non ce ne sono molti nemmeno per lunghi periodi, e saranno molto più veloci di materializzarli al volo da tabelle temporanee o ctes ricorsivi.

+1

Una soluzione intermedia, se non si desidera avere una tabella di date è usare una [più piccola] tabella di numeri (diciamo da 0 a 1000) e avere qualcosa come selezionare cast (@minDate come datetime) + Val da tblNumbers dove val <= (cast (@minDate come datetime) - cast (@maxDate come datetime)) (assumendo Val è il campo INT in tblNumber, con valori 0, 1, 2 ...) – mjv

+0

Grazie, I Ho deciso di andare con il tavolo fisico, mi sembra una cattiva idea avere un tavolo con una colonna che memorizza solo le date. –

+2

Non è una cattiva idea. Va contro il normale modo di pensare orientato all'algoritmo dei programmatori, tutto qui. In realtà molti raccomandano di avere una tabella con solo numeri, da 0 a 1 mil. o simili, da utilizzare in join e query simili alla tua. –

1

qualcosa di simile:

CREATE FUNCTION GetDates(@StartDate DateTime, @EndDate DateTime) 

RETURNS @Dates Table (aDate DateTime Primary Key Not Null) 
AS 
BEGIN 
Declare @ThisDate DateTime Set @ThisDate = @StartDate 
While @ThisDate < @EndDate begin  
     Insert @Dates (aDate) Values(@THisDate)  
     Set @ThisDate = @ThisDate + 1 
End 
RETURN 
END 
GO 

assicurarsi @EndDate è dopo @StartDate ... Aggiungi parametro di ingresso controllando fa in modo, o potrebbe correre per sempre se si passa risale all'indietro

+0

Looping sarà più lento. CTE sarà una scelta migliore – Faiz

+0

@Faiz, sono curioso puoi mostrare per es. di soluzione CTE? –

3

Se si sceglie di (o necessario) andare con un tavolo ad hoc e non una permanente, questo lo farebbe:

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

E una chiamata di prova:

DECLARE 
    @MinDate datetime 
,@MaxDate datetime 

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

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

Wierd - questo è il terzo post SO oggi che ha coinvolto i tavoli Tally. Deve esserci qualche strana attività di macchie solari in corso. Ecco le 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?

+0

Doh! Non l'ho visto prima di elaborare la stessa soluzione. –

Problemi correlati