Выбор всех дат из таблицы в диапазоне дат, включая 1 строку на пустую дату - PullRequest
1 голос
/ 19 января 2012

Я пытаюсь реорганизовать некоторый код на веб-сайте ASP.Net и у меня возникла проблема с хранимой процедурой, которую я пишу.

То, что я хочу сделать, это получить диапазон дат, а затем выбрать все данные в этом диапазоне из таблицы, НО, если дата не указана, мне все равно нужно выбрать строку.

Моя идея для этого, как вы можете видеть в приведенном ниже коде, состоит в том, чтобы создать временную таблицу и заполнить ее всеми датами в моем диапазоне дат, а затем соединить это с таблицей, из которой я выбираю, однако это не работает. Я что-то здесь не так делаю? Столбец 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<=@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 

Ответы [ 2 ]

3 голосов
/ 19 января 2012

Есть несколько способов справиться с отсутствующими строками, но все они связаны с наличием другого набора данных для объединения с текущими результатами.

Это может быть получено из ваших результатов, созданных 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 голосов
/ 20 января 2012

Ну, идея та же самая, но я бы написал функцию, которая возвращает таблицу со всеми датами в периоде. Посмотрите на это:

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())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...