【问题标题】:Why is this SQL case statement behaving like an OR statement?为什么这个 SQL case 语句表现得像 OR 语句?
【发布时间】:2018-11-19 23:51:46
【问题描述】:

考虑以下查询:

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

我正在尝试返回单个记录/行。有问题的特定租赁在 dbo.RentalRateType 表中有 2 条记录,当我运行上述查询时,我得到 2 个结果,但我希望它在 case where 中的第一个匹配时短路。

基本上,最终用户可以填写多种费率类型,比您在本示例中看到的要多,并且每种类型都有优先级。 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

虽然我在这里,但如果存在,我愿意以更有效的方式处理此问题。

【问题讨论】:

  • 我不确定你的具体要求,但你得到两个结果的原因是因为两者都满足 case 表达式的条件......也许你只是在寻找一个 TOP 1 和一个根据您要查找的内容订购?
  • 您为什么将inner join 写成left outer join 并引用不允许空值的where 子句(... and rt.TypeId = ...) 中的右侧表格?跨度>
  • @HABO 我需要考虑没有输入费率但仍返回记录的情况(左连接的原因)-编辑-是的,我明白您对 WHERE 子句的意思。那是因为我正在移动它进行测试(在 ON (...) 内。
  • @HABO 我会修正我的例子
  • @ZLK 对。我的目标是返回单行。如果用户的费率类型为 6,则使用那个,否则使用 1。现在在我的实际应用程序中,大约有 5 种不同的费率类型,每种都有优先级。

标签: sql-server tsql sql-server-2016


【解决方案1】:

改用apply,这些是获取“前 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

【讨论】:

    猜你喜欢
    • 2014-07-09
    • 2018-07-04
    • 2012-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多