Почему этот оператор SQL ведет себя как оператор OR? - PullRequest
0 голосов
/ 20 ноября 2018

Рассмотрим следующий запрос:

declare @RentalId int = 1

SELECT 
     r.RentalId
    ,r.[Name]
    ,rt.TypeId


FROM dbo.Rental r
LEFT JOIN dbo.RentalRateType rt ON (
    r.RentalId = rt.RentalId
    AND rt.TypeId = (
        case when rt.TypeId = 6 and coalesce(rt.[Max], rt.[Min]) is not null then 6
         when rt.TypeId = 1 and coalesce(rt.[Max], rt.[Min] is not null then 1 
        else -1 end
))
WHERE r.RentalId = @RentalId

Я пытаюсь вернуть одну запись / строку.Конкретный рассматриваемый прокат имеет 2 записи в таблице dbo.RentalRateType, и когда я запускаю вышеуказанный запрос, я получаю 2 результата, но я хочу, чтобы он замкнулся при первом совпадении в case where.

* 1007.* По сути, конечный пользователь может заполнить несколько типов ставок, больше, чем вы видите в этом примере, и у каждого из этих типов есть приоритет.6 является наивысшим приоритетом в примере.

Итак, я получаю следующий результат:

RentalId |   Name   | TypeId
----------------------------
1          Super Car  6    
1          Super Car  1

Но если тип (6) существует, я ожидаю, что вернется только первая строка выше.

Я, должно быть, скучаю по чему-то глупому.Это работает, как и ожидалось:

case when 1=2 then 6
     when 1=1 then 1 
     else -1 end

Пока я здесь, я открыт для более эффективного способа справиться с этим, если существует.

1 Ответ

0 голосов
/ 20 ноября 2018

Используйте взамен apply, это эффективный способ получить запросы "top n":

SELECT
    r.RentalId
  , r.[Name]
  , oa.TypeId
FROM dbo.Rental r
OUTER APPLY (
        SELECT TOP (1)
            rt.TypeId
        FROM dbo.RentalRateType rt
        WHERE r.RentalId = rt.RentalId
        ORDER BY
            rt.TypeId DESC
    ) oa
WHERE r.RentalId = @RentalId
...