Предложение WHERE, в котором некоторые параметры могут быть нулевыми.

Мне поручено получить количество записей, которые попадают во время начала и время окончания, в то время как возможно фильтруются по @aircraftId, @instructorId и @reservationId (поэтому он игнорирует себя при подсчете). Все три параметра могут принимать значение NULL, поэтому они могут передаваться или не передаваться, поэтому запрос должен будет фильтроваться на основе их наличия или отсутствия. Я могу сделать это с помощью динамического Sql, но я предпочитаю избегать этого, главным образом потому, что отладка будет утомительна для тех, кто будет иметь дело с этим позже.

Возможно ли это (я предполагаю, что это возможно) в одном запросе? Или это одна из тех ситуаций, когда мне приходится брать набор и сокращать его с другими параметрами, если они присутствуют?

SELECT  COUNT(*)
FROM    AVMAN.Reservation
WHERE   ( @aircraftid IS NULL
            OR ( @aircraftid IS NOT NULL
                AND AircraftId = @aircraftid
                )
        )
        OR ( @InstructorId IS NULL
                OR ( @InstructorId IS NOT NULL
                    AND InstructorUserId = @InstructorId
                )
            )
        AND ( ( -- start during the range
                StartTime >= @StartTime
                AND StartTime < @EndTime
                )
                OR ( -- end during the range 
                    EndTime > @StartTime
                    AND EndTime <= @EndTime
                    )
                OR ( -- start before the range and end after it
                    StartTime < @StartTime
                    AND EndTime > @EndTime
                    )
            )
        AND ( @ReservationId IS NULL
                OR ( ReservationId IS NOT NULL
                    AND ReservationId = @ReservationId
                    )
            )

person Yatrix    schedule 01.09.2015    source источник
comment
Возможный дубликат: stackoverflow.com/questions/17850726/   -  person joshhendo    schedule 01.09.2015
comment
Вы можете упростить: @aircraftid IS NULL OR ( @aircraftid IS NOT NULL AND AircraftId = @aircraftid) До: @aircraftid IS NULL OR AircraftId = @aircraftid   -  person joshhendo    schedule 01.09.2015


Ответы (2)


Во-первых, в вашем исходном SQL у вас есть ИЛИ, а не И, что отбросит ваши результаты.

Чтобы привести в порядок фильтры по самолетам, инструктору и бронированию, вы можете сделать следующее:

SELECT  COUNT(*)
FROM    AVMAN.Reservation
WHERE   
    ISNULL( @AircraftId, AircraftId ) = AircraftId 
    AND
    ISNULL( @InstructorId, InstructorId ) = InstructorId 
    AND
    ISNULL( @ReservationId, ReservationId ) = ReservationId 
    AND 
    ( ( -- start during the range
            StartTime >= @StartTime
            AND StartTime < @EndTime
            )
            OR ( -- end during the range 
                EndTime > @StartTime
                AND EndTime <= @EndTime
                )
            OR ( -- start before the range and end after it
                StartTime < @StartTime
                AND EndTime > @EndTime
                )
        )

ISNULL в основном сравнивает AircraftId с @AircraftId, когда он не равен нулю, и сравнивает с AircraftId (который, очевидно, всегда будет одним и тем же), когда @AircraftId имеет значение null.

person Sam Peacey    schedule 01.09.2015

Я не уверен, но попробуйте использовать CASE в предложении WHERE, как это

SELECT  COUNT(*)
FROM    AVMAN.Reservation
WHERE CASE
        WHEN @aircraftid IS NULL THEN 1 
        WHEN @aircraftid IS NOT NULL AND  AircraftId = @aircraftid THEN 1 
     END = 1 
     AND 
     CASE 
        WHEN @InstructorId IS NULL  THEN 1
        WHEN @InstructorId IS NOT NULL AND InstructorUserId = @InstructorId THEN 1
     END = 1
     AND ( ( -- start during the range
                StartTime >= @StartTime
                AND StartTime < @EndTime
                )
                OR ( -- end during the range 
                    EndTime > @StartTime
                    AND EndTime <= @EndTime
                    )
                OR ( -- start before the range and end after it
                    StartTime < @StartTime
                    AND EndTime > @EndTime
                    )
            )
        AND 
         CASE 
            WHEN @ReservationId IS NULL THEN 1
            WHEN ReservationId IS NOT NULL AND ReservationId = @ReservationId THEN 1
         END = 1
person Chanom First    schedule 01.09.2015