【问题标题】:SQL Server : case when in where clauseSQL Server:在where子句中的情况
【发布时间】:2016-10-20 18:41:41
【问题描述】:

你能教我在我的情况下我做错了什么吗? :)

我正在选择发票和还款。

错误

消息 4145,第 15 级,状态 1,第 10 行
在预期条件的上下文中指定的非布尔类型表达式,靠近“结束”。

代码:

select 
    I.subject1, R.subject2
from
    dbo.invoice I
left join 
    dbo.repayments R on I.subject1 = R.subject2
where
    case
       when R.subject2 is not null and R.remains_due > 0 
          then R.remains_due
       when R.subject2 is not null and R.remains_due = 0 
          then I.remains_due
       when R.subject2 is not null and R.due_date <= GETDATE() 
          then R.due_date
       when R.subject2 is null and I.due_date <= GETDATE() 
          then I.due_date
    end

【问题讨论】:

  • WHERE 子句中使用AND/OR 而不是case 表达式通常会更好。
  • 你的 case 表达式返回一个值,现在你需要将它与某物进行比较。
  • 我需要“case”,因为“then”对我很重要。你说的比较?你能告诉我更多吗?
  • 您可能根本不需要“then”...是的,您的 case 表达式返回一个值。该怎么办?
  • 那我如何告诉程序在没有“then”的情况下获取特定属性?

标签: sql sql-server tsql


【解决方案1】:

下面展示了如何在WHERE clause中使用搜索条件。

SELECT
  ColumnB,
  ColumnA
FROM
  TableA
WHERE
  ColumnA =  CASE WHEN ColumnB IS NULL THEN 'Test AA'
                  WHEN ColumnB IS NOT NULL THEN 'Test BB'
                  ELSE 'Test CC' END

您的查询不正确。查询如下:

SELECT
  ColumnB,
  ColumnA
FROM
  TableA
WHERE
  -- Where is ColumnA???
  -- Return types must be same type!
  CASE WHEN ColumnB IS NULL THEN 'Test AA' -- VARCHAR?
       WHEN ColumnB IS NOT NULL THEN 1 -- INT ?
       ELSE '2016.10.20' END -- DATETIME?

更新

select 
    I.subject1, 
    R.subject2
from
    dbo.invoice I LEFT join 
    dbo.repayments R on I.subject1 = R.subject2
WHERE
     (
        R.subject2 is not NULL AND
        R.remains_due >= 0  AND
        R.due_date <= GETDATE() 
     ) OR
     (
        R.subject2 is NULL AND
        I.due_date <= GETDATE() AND
        I.remains_due >= 0
      )

【讨论】:

  • 感谢您的回复! :)
  • 列保持_到期是钱,列到期日是日期时间。例如,我应该将其转换为 varchar 吗?我不确定我是否完全理解你的回答。
  • 您要选择哪些调用?
  • 你是对的。结果是正确的。我很困惑我们公司在到期日之后有超过 1 万张发票:/ 我会问我的大师,我会回复他告诉我的内容。非常感谢!
  • 我的大师告诉我这是正确的!他告诉我他想使用 CASE 语句,因为我们将在 CRM 系统的模板中使用它。
【解决方案2】:

试试

select 
    I.subject1, R.subject2
from
    dbo.invoice I
left join 
    dbo.repayments R on I.subject1 = R.subject2
where

       R.subject2 is not null and R.remains_due > 0 
          AND
        R.subject2 is not null and R.remains_due = 0 
          AND
        R.subject2 is not null and R.due_date <= GETDATE() 
          AND
        R.subject2 is null and I.due_date <= GETDATE() ;

【讨论】:

  • 谢谢,但是条件中没有逻辑:/
【解决方案3】:

我认为您完全误解了 WHERE 子句。 where 子句是结果集中要包含哪些记录的条件。例如:给我发票 >= 某个日期范围的所有记录,或金额 = 您要查找的某个值的发票。这些只需要返回逻辑 TRUE 或 FALSE。

使用 case 语句将在您的字段列表中根据条件确定您想要返回的值。在这种情况下,在行的特定条件下,您希望返回特定的内容以显示给用户。

select 
      I.subject1, 
      R.subject2,
      case when R.subject2 is not null and R.remains_due > 0 
              then R.remains_due
           when R.subject2 is not null and R.remains_due = 0 
              then I.remains_due
           end  as AmountDue,
      case when R.subject2 is not null and R.due_date <= GETDATE() 
              then R.due_date
           when R.subject2 is null and I.due_date <= GETDATE() 
              then I.due_date
           end   DueDate
   from
      dbo.invoice I
         left join dbo.repayments R 
            on I.subject1 = R.subject2

【讨论】:

    【解决方案4】:

    CASE EXPRESSION 的基本用途是 - 评估某个表达式,根据表达式的结果返回 单值

    现在你几乎在 WHERE 子句中做对了。案例表达式返回一些值,但在 WHERE 子句中,这些值需要与其他一些值进行比较,这是您的查询中缺少的部分。您也可以尝试这种方式以获得正确的结果。

    ...
    where 
    1 = case
          when R.subject2 is not null and R.remains_due > 0 
             then 1
          when R.subject2 is not null and R.remains_due = 0 
             then 1
          when R.subject2 is not null and R.due_date <= GETDATE() 
             then 1
          when R.subject2 is null and I.due_date <= GETDATE() 
            then 1
       end
    

    【讨论】:

    • 谢谢,1 = 机箱很酷。但是你的代码给了我 0,5 m 记录:X
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-31
    • 1970-01-01
    • 2021-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多