Sql 从日期范围内的表中选择所有日期,每个空日期包括一行

Sql 从日期范围内的表中选择所有日期,每个空日期包括一行,sql,sql-server-2008,stored-procedures,Sql,Sql Server 2008,Stored Procedures,我试图重构ASP.Net网站中的一些代码,但我正在编写的存储过程出现问题 我想做的是获取一个日期范围,然后从表中选择该范围内的所有数据,但如果没有日期,我仍然需要选择一行 正如您在下面的代码中看到的,我的想法是创建一个临时表,并用我的日期范围内的所有日期填充它,然后将其加入到我选择的表中,但这不起作用。我做错什么了吗?在此联接中,tempDate列始终为null,但是我已检查了该表,并且该表中定义了数据 -- Parameters DECLARE @DutyDate datetime='2012

我试图重构ASP.Net网站中的一些代码,但我正在编写的存储过程出现问题

我想做的是获取一个日期范围,然后从表中选择该范围内的所有数据,但如果没有日期,我仍然需要选择一行

正如您在下面的代码中看到的,我的想法是创建一个临时表,并用我的日期范围内的所有日期填充它,然后将其加入到我选择的表中,但这不起作用。我做错什么了吗?在此联接中,tempDate列始终为null,但是我已检查了该表,并且该表中定义了数据

-- 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<=@EndDate
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 

有几种方法可以处理丢失的行,但都是关于使用另一组数据与当前结果相结合

这可能来自您的结果,由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

这将日历模板放在左侧,因此使许多查询变得更容易,因为您知道日历的日期字段总是填充的,总是一个只有日期的字段,没有时间部分值,是有序的,易于分组,等等。

好吧,想法是一样的,但我会编写函数,它返回包含期间中所有日期的表。看看这个:

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())

CTE可以做到这一点,看看+1:日历表是一种方式,易于填充,而且总是有用的。Google celko calendar table可获取更多信息和其他使用方法的提示。感谢您的帮助,这完美解决了问题,我也将研究如何使用日历表。谢谢你的信息