【问题标题】:Use if in where statement在 where 语句中使用 if
【发布时间】:2019-08-05 08:09:39
【问题描述】:

我有 4 张桌子:

  1. Table_op_type
  2. Table_maintenancetype
  3. Table_repair_time
  4. Table_repair_type

每个表都有一个可以为真或假的列,我有一个 Table_maintenancereport,当我选择 Table_maintenancereport 和每个表中的一行时,我有一个 Table_maintenancereport 中的许多列和 4 列外键从 4 上表给出是真正的代码工作正常,但是当从表中返回多行时会出现此错误。

子查询返回超过 1 个值。当子查询跟随 =、!=、、>= 或子查询用作表达式时,这是不允许的。

我该如何解决?

我的代码是:

SELECT *
FROM Table_maintenancereport
WHERE mtypeid IN (IIF(@smtype = 1, (SELECT Table_maintenancetype.id FROM Table_maintenancetype WHERE enable_search = 1), mtypeid))
  AND op_typeid IN (IIF(@sop IN (1), (SELECT Table_op_type.id FROM Table_op_type WHERE enable_search = 1), op_typeid))
  AND repaire_timeid IN (IIF(@stime IN (1), (SELECT Table_repair_time.id FROM Table_repair_time WHERE enable_search = 1), repaire_timeid))
  AND repaire_typeid IN (IIF(@stype = 1, (SELECT Table_repair_type.id FROM Table_repair_type WHERE enable_search = 1), repaire_typeid));

【问题讨论】:

  • 编写整个代码示例,仅此输入并不清楚。
  • mtypeid IN ( iif(@smtype=1,(select Table_maintenancetype.id from Table_maintenancetype where enable_search=1),mtypeid))这个东西完全没有意义,你来这里的目的是什么?
  • 问题不在于IIF,而是您的子查询;该错误准确地告诉您问题所在。然而,这似乎你会更好地使用一些正确的JOIN 语法和正确的布尔逻辑。
  • 您的每个子查询都返回多个值,即其他 3 个表返回多个值,请尝试使用 distinct。改用 case 表达式重写语句

标签: sql sql-server sql-server-2017


【解决方案1】:

您需要修复where 条件。您可以使用基本的逻辑运算符来做到这一点。 iif()case() 表达式不能返回集合。

所以:

WHERE (@smtype <> 1 OR
       mtypeid IN (SELECT Table_maintenancetype.id FROM Table_maintenancetype WHERE enable_search = 1)
      ) AND
      (@sop <> 1 OR
       op_typeid IN (SELECT Table_op_type.id FROM Table_op_type WHERE enable_search = 1)
      ) AND
      (@stime <> 1 OR
       repaire_timeid IN (SELECT Table_repair_time.id FROM Table_repair_time WHERE enable_search = 1)
      ) AND
      (@stype <> 1 OR
       repaire_typeid IN (SELECT Table_repair_type.id FROM Table_repair_type WHERE enable_search = 1)
      );

【讨论】:

    【解决方案2】:

    如果我正确地解释了您正在尝试做的事情:

    SELECT *
    FROM Table_maintenancereport mr
    LEFT OUTER JOIN Table_maintenancetype mt ON mr.mtypeid = mt.id AND enable_search = 1
    LEFT OUTER JOIN Table_op_type ot ON mr.op_typeid = ot.id AND enable_search = 1
    LEFT OUTER JOIN Table_repair_time rt ON mr.repaire_timeid = rt.id AND enable_search = 1
    LEFT OUTER JOIN Table_repair_type rty ON mr.repaire_typeid = rty.id AND enable_search = 1
    WHERE (ISNULL(@smtype,-1) != 1 OR mt.id IS NOT NULL)
    AND (ISNULL(@sop,-1) != 1 OR ot.id IS NOT NULL)
    AND (ISNULL(@stime,-1) != 1 OR rt.id IS NOT NULL)
    AND (ISNULL(@stype,-1) != 1 OR rty.id IS NOT NULL)
    

    因此,对于每个@variable,如果将其设置为 1,则相应的字段必须是启用搜索的 id 之一才能出现在输出中。如果变量未设置为 1,则不会过滤相应的字段。

    【讨论】:

      【解决方案3】:

      也许您可以在 where 子句中使用CASE WHEN 语句,例如:

         select
          *
      from
          Table_maintenancereport
      where
          case
              when @smtype = 1 then mtypeid in (
                  select Table_maintenancetype.id
              from
                  Table_maintenancetype
              where
                  enable_search = 1)
              else mtypeid = mtypeid end
      
          ....
      

      【讨论】:

      • 此代码不起作用 iif 和 case 有类似但从子查询返回值的问题
      • @Mehrdad 然后您可以对每个子查询使用top 1distinct
      猜你喜欢
      • 1970-01-01
      • 2019-07-14
      • 2013-03-02
      • 1970-01-01
      • 2016-02-02
      • 1970-01-01
      • 1970-01-01
      • 2016-09-18
      • 2021-07-17
      相关资源
      最近更新 更多