2009-09-08 14 views
5

मुझे एक ऐसा फ़ंक्शन बनाना होगा जो निरंतर तिथियों की एक तालिका लौटाए। मैं एक न्यूनतम & अधिकतम तिथि में गुजरता हूं।निरंतर तिथियों की वापसी temp तालिका

मैं इसे सक्षम होने की अपेक्षा इस तरह के नाम से जाना:

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

मैं वर्तमान में एक संग्रहीत proc है कि इस करता है, लेकिन आवश्यकताओं को बदल दिया है और अब मैं एक संघ के भीतर से दिए गए डेटा शामिल करने की जरूरत है :

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) 

समस्या है, तथापि, मैं eggheadcafe पर गेल एरिक्सन [एमएस] द्वारा एक पोस्ट के अनुसार 100 से अधिक होने की प्रत्यावर्तन निर्धारित करने की आवश्यकता है कि, इस समय समर्थित नहीं है।

बस में तारीख के साथ एक वास्तविक (अस्थायी नहीं) तालिका बनाने के बिना, वहाँ यह करने के लिए एक तरीका है?

मैं एसक्यूएल सर्वर 2005 का उपयोग कर रहा हूं।

+0

यह प्रत्यावर्तन स्तर 100 की तुलना में अधिक मान पर सेट है, तो मैं सही अधिकतम समर्थित स्तर 2^15 है याद रखना संभव नहीं है। – Faiz

उत्तर

6

गुजारें सकता आपका सबसे अच्छा विकल्प वास्तव में तारीखों की एक भौतिक तालिका है। इतने लंबे समय तक बहुत से लोग नहीं हैं, और अस्थायी तालिकाओं या रिकर्सिव सीटी से उन्हें उड़ाने से कहीं अधिक तेज होंगे।

+1

यदि आप तिथियों की एक तालिका नहीं चाहते हैं तो एक इंटरमीडिएट समाधान है [संख्या] संख्याओं की संख्या [0 से 1000 तक) और जैसे कुछ कास्ट करें (@minDate डेटाटाइम के रूप में) + वैल tblNumbers से जहां वैल <= (कास्ट (@minDate डेटाटाइम के रूप में) - कास्ट (@maxDate डेटाटाइम के रूप में)) (मानते हुए वैल tblNumber में INT फ़ील्ड है, मान 0, 1, 2 ...) – mjv

+0

धन्यवाद, मैं मैंने भौतिक तालिका के साथ जाने का फैसला किया है, यह सिर्फ एक तारीख है जो एक कॉलम के साथ एक टेबल रखने के लिए एक बुरा विचार है। –

+2

कोई बुरा विचार नहीं है। यह सोचने वाले प्रोग्रामर के सामान्य एल्गोरिदम उन्मुख तरीके से है, यह सब कुछ है। दरअसल कई लोग 0 से 1 मिलियन तक, केवल संख्याओं के साथ एक टेबल रखने की सलाह देते हैं। या इसी तरह, आपके जैसे जोड़ों और प्रश्नों में उपयोग करने के लिए। –

1

कुछ इस तरह:

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 

यकीन @EndDate बनाने @startdate के बाद है ... इनपुट पैरामीटर की जाँच करने के लिए सुनिश्चित करता है जोड़ें, या इसे हमेशा के लिए बना रहेगा यदि आप यह पीछे की ओर तारीखें

+0

लूपिंग धीमा हो जाएगा। सीटीई बेहतर विकल्प होगा – Faiz

+0

@ फ़ैज़, मैं उत्सुक हूं कि आप दिखा सकते हैं उदा। सीटी समाधान का? –

3

आप कर सकते हैं (या करने की जरूरत है) एक तदर्थ मेज और न कोई स्थायी पता नहीं के साथ जाना है, तो यह यह करना होगा:

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

और एक परीक्षण कॉल:

DECLARE 
    @MinDate datetime 
,@MaxDate datetime 

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

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

वियर्ड - यह तीसरी एसओ पोस्ट है जिसमें टैली टेबल शामिल हैं। कुछ अजीब सनस्पॉट गतिविधि चलनी चाहिए। यहाँ 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

दोह! उसी समाधान को काम करने से पहले इसे नहीं देखा। –

संबंधित मुद्दे