【问题标题】:How can I select rows with value of No or NULL when the parameter = 'No' and rows with value of 'Yes' when the parameter ='Yes'如何在参数 = 'No' 时选择值为 No 或 NULL 的行,以及在参数 ='Yes' 时选择值为 'Yes' 的行
【发布时间】:2019-06-20 17:17:08
【问题描述】:

我需要根据参数“@HotList”选择行。

当 '@HotList' = 'Yes' 时,我需要提取 'co.ro_HotList' 字段包含 'Yes' 值的所有行 当 '@HotList' = 'No' 时,我需要提取 'co.ro_HotList' 字段包含 'No' 或 null 值的所有行

我可以仅根据参数选择值为“是”或“否”的行,但无法弄清楚当参数为“否”时如何选择空行。如何修改提供的代码以实现此目的?

我尝试在 where 子句中使用 case 语句,但没有成功。

SELECT ds.*                     
FROM Rotex_DailyShipmentNotShip ds
left outer join CRM_MSCRM..SalesOrder co ON ds.SOP#=co.Name 
WHERE co.ro_HotList = @HotList

【问题讨论】:

  • 除了Y N Null还有其他选择吗?

标签: sql sql-server reporting-services ssrs-2012


【解决方案1】:

在哪里试试这个:

ISNULL(co.ro_HotList,'No') = @HotList

ISNULL 将对第二个输入评估一个空值,因此在您的情况下,所有空值都被视为“否”。

【讨论】:

  • 如果值为“是”或“否”,此语句是否仍会传递 co.ro_HotList 字段?
  • @贾斯汀韦德。是的。 ISNULL 会将表达式计算为实际值,除非它为 null 然后结果是第二个输入。
  • COALESCE 是另一种方法。 COALESCE 计算为第一个非空值。
【解决方案2】:

Keith 的答案是正确的,但为了完整起见,您提到您尝试CASE,这就是应该如何使用CASE

  WHERE CASE WHEN co.ro_HotList IS NULL 
             THEN 'No'
             ELSE co.ro_HotList
        END  = @HotList

【讨论】:

    【解决方案3】:

    过滤条件可以写成如下图:

    SELECT ds.*                     
    FROM Rotex_DailyShipmentNotShip ds
    left outer join CRM_MSCRM..SalesOrder co ON ds.SOP#=co.Name 
    WHERE @HotList = 'Yes' and co.ro_HotList = 'Yes'
       OR @HotList = 'No' and (co.ro_HotList = 'No' or co.ro_HotList is null)
    

    【讨论】:

    • 您可能需要括号来分隔 OR 条件
    • @JuanCarlosOropeza AND 的优先级高于 OR,因此它应该可以按预期工作。不过,我同意这对普通读者来说可能更清楚。
    【解决方案4】:

    对 OP 问题的几个答案是有效的,因为它们返回了预期的结果,但大多数答案都是低效的,因为它们妨碍了正确使用索引。

    在表达式(如 case 表达式或函数)中包含列名可防止 SQL Server 使用索引。

    带有 OR 运算符和参数条件的谓词也会妨碍有效的执行计划。

    有几种方法可以有效地构造查询:

    添加计算列

    添加一个计算列,例如:

    ALTER TABLE ADD HotList AS ISNULL(ro_HotList, 'No')

    并将其编入索引。然后查询将更简单且索引友好:

    WHERE HotList = @HotList

    智能客户端应用程序

    客户端应用程序可能足够聪明,可以执行以下操作(伪代码)

    If HostListParameter is "No" then execute the query:
       SELECT <column list>
       FROM Whatever
       WHERE ro_HostList = 'No' OR ro_HostList IS NULL
    Else execute this other query:
       SELECT <column list>
       FROM Whatever
       WHERE ro_HostList = @HotList
      Invalid parameter
    

    将 T-SQL Batch 与逻辑结合使用

    不是执行单个选择语句,而是执行具有逻辑的批处理

    IF @HostList = 'No'
    BEGIN
       SELECT <column list>
       FROM Whatever
       WHERE ro_HostList = 'No' OR ro_HostList IS NULL 
    END
    ELSE
    BEGIN
       SELECT <column list>
       FROM Whatever
       WHERE ro_HostList = @HotList
    END
    

    使用存储过程

    您可以创建一个执行与前面的 T-SQL 批处理相同的逻辑的存储过程

    使用OPTION(RECOMPILE)

    添加选项(重新编译)

    将 OPTION(RECOMPILE) 添加到 Impaler 答案会导致可以使用索引的更好的执行计划,但它也会阻止计划重用。

    但很少使用选择性低的非覆盖索引

    如果一列包含的值很少,则非覆盖索引几乎是无用的。

    在这种情况下,我认为该列只能包含“是”、“否”或 NULL。所以索引它不会提高性能。最好的答案是 KeithL 的。

    【讨论】:

      猜你喜欢
      • 2020-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-07
      • 2012-03-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多