2012-01-19 67 views
1

我想重構ASP.Net網站中的某些代碼,並且遇到了我正在編寫的存儲過程的問題。從一個日期範圍內的表中選擇所有日期,並且每個空日期包括1行

我想要做的是獲取日期範圍,然後從表中選擇該範圍內的所有數據,但如果日期不存在,我仍然需要選擇一行。

我的想法如下,您可以在下面的代碼中看到創建一個臨時表,然後將其填充到我的日期範圍內的所有日期,然後將其加入到我選擇的表中,但這不起作用。我在這裏做錯了什麼? tempDate列在這個連接中始終爲空,但是我已經檢查了表,並且它鬆散地包含了數據。

-- Parameters 
DECLARE @DutyDate datetime='2012-01-01 00:00:00' 
DECLARE @InstructorID nvarchar(2) = N'29' 

DECLARE @datesTBL TABLE (tempDate DATETIME) 

-- Variables 
DECLARE @StartDate DATETIME 
DECLARE @EndDate DATETIME 

SELECT 
    @StartDate =StartDate, 
    @EndDate = EndDate 
FROM 
    DutyPeriodTbl 
WHERE 
(StartDate <= @DutyDate) 
AND 
(EndDate >= @DutyDate) 


DECLARE @d DATETIME = @StartDate 
WHILE @d<[email protected] 
BEGIN 
    INSERT INTO @datesTBL VALUES (CONVERT(DATETIME, @d, 102)) 
    SET @d=DATEADD(day,1,@d) 
END 

SELECT 
    dt.tempDate , 
    InstructorID,   EventStart, 
    EventEnd,    cancelled, 
    cancelledInstructor, 
    EventType,    DevName, 
    Room,     SimLocation, 
    ClassLocation,   Event, 
    Duration,    TrainingDesc, 
    Crew,     Notes, 
    LastAmended,   InstLastAmended, 
    ChangeAcknowledged,  Type, 
    OtherType,    OtherTypeDesc, 
    CourseType 
FROM 
    OpsInstructorEventsView iv 
LEFT OUTER JOIN 
    @datesTBL dt 
ON 
    CONVERT(DATETIME, iv.EventStart, 102) = CONVERT(DATETIME, dt.tempDate, 102) 
WHERE 
    InstructorID = @InstructorID 
AND 
    EventStart BETWEEN CONVERT(DATETIME, @StartDate, 102) AND CONVERT(DATETIME, @EndDate, 102) 
ORDER BY 
    EventStart 
+0

的CTE可以做到這一點,看看http://stackoverflow.com/questions/5899829/sql -server-how-to-select-all-days-in-a-date-range-even-if-no-data-exists-for-so –

回答

3

有幾種處理缺失行的方法,但都是關於將另一組數據與當前結果結合使用。

通過使用永久模板加入反對,可以從您的結果,由CTE或其他過程(如您的示例)創建的結果或(我的首選)導出。

您的案例中的模板可能只是一個日期表,就像您的@datesTBL一樣。不同之處在於它提前創建,例如100年的日期。

然後將查詢可能類似於你的榜樣,但我會嘗試以下...

SELECT 
    dt.tempDate , 
    InstructorID,   EventStart, 
    EventEnd,    cancelled, 
    cancelledInstructor, 
    EventType,    DevName, 
    Room,     SimLocation, 
    ClassLocation,   Event, 
    Duration,    TrainingDesc, 
    Crew,     Notes, 
    LastAmended,   InstLastAmended, 
    ChangeAcknowledged,  Type, 
    OtherType,    OtherTypeDesc, 
    CourseType 
FROM 
    @datesTBL dt 
LEFT OUTER JOIN 
    OpsInstructorEventsView iv 
    ON iv.EventStart >= dt.tempDate 
    AND iv.EventStart < dt.tempDate + 1 
    AND iv.InstructorID = @InstructorID 
WHERE 
     dt.tempDate >= @StartDate 
    AND dt.tempDate <= @EndDate 
ORDER BY 
    dt.tempDate, 
    iv.EventStart 

這給左側的日曆模板,所以讓你知道很多更容易查詢日曆的日期字段總是被填充,始終是一個只有日期(沒有時間部分)的值,是爲了,簡單到GROUP BY等

+0

+1:一個'Calendar'表是要走的路,簡單填充並始終有用。谷歌的「celko日曆表」獲取更多信息以及以其他方式使用它們的提示。 – Tony

+0

感謝您解決這個問題,我會考慮使用日曆表。謝謝(你的)信息 – Purplegoldfish

0

好吧,想法是一樣的,但我會寫函數,返回包含期間所有日期的表格。看看這個:

Create Function [dbo].[Interval] 
(
    @DateFrom Date, 
    @DateTo Date 
) 
Returns @tab Table 
    (
     MyDate DateTime 
    ) 
As 
Begin 
    Declare @Days int 
    Declare @i int 
    Set @Days = DateDiff(Day, @DateFrom, @DateTo) 

    Set @i = 0; 
    While (@Days > @i) 
    Begin 
     Insert Into @tab(MyDate) 
      Values (DateAdd(Day, @i, @DateTo)) 
     Set @i = @i + 1 
    End 
    return 
End 

和重用,當您需要它的功能..

Select * 
From [dbo].[Interval]('2011-01-01', GETDATE()) 
相關問題