【问题标题】:SQL CASE returning wrong valuesSQL CASE 返回错误值
【发布时间】:2016-08-26 19:50:36
【问题描述】:

我编写了以下查询,但 CASE 语句返回的值不正确。当 soaddr 有一个值而不是从 soaddr 返回值时,它将从 arcust 返回不正确的值。但是,如果我更改 else 语句以从 soaddr 中提取值,那么它将返回一个 NULL 值。我做错了什么?

SELECT DISTINCT a.custno, b.company,
    CASE WHEN c.address1 = NULL THEN b.address1
    ELSE b.address1
    END as address,
    CASE WHEN c.city = NULL THEN b.city
    ELSE b.city
    END as city,
    CASE WHEN c.addrstate = NULL THEN b.addrstate
    ELSE b.addrstate
    END as addrstate,
    CASE WHEN c.zip = NULL THEN b.zip
    ELSE b.zip
    END as zip,
    invno, descrip, qtyshp, price, extprice, b.tax, invdte 
FROM artran a
LEFT JOIN arcust b ON a.custno = b.custno
LEFT JOIN soaddr c ON a.custno = c.custno

【问题讨论】:

  • 当soaddr 不为空时,你不想要else c.address1 吗?或者你可以使用coalesce(c.address1,b.address1) 使用soaddr,否则使用arcust.address1。
  • 我做了很多 ETL 工作,很多时候我不仅要检查文本值是否为 null,我还需要检查它是否为空字符串,因此我使用 ISNULL(, '') 为空。请看msdn.microsoft.com/en-us/library/ms184325.aspx

标签: sql sql-server case


【解决方案1】:

您不能用 = 将值与 NULL 进行比较。 使用为空。

CASE WHEN c.address1 IS NULL THEN b.address1
 ELSE b.address1

【讨论】:

  • 少了周围的 ** 是.. :P... 它在两个评估中都返回 b.address1 ......对我来说似乎很奇怪我认为 else 应该是 c.address1。
  • 另外,考虑使用 isnull( c.address1, b.address1 ) 或 coalesce( c.address1, b.address1)。 coalesce 的额外好处是可以查看任意数量的字段或返回默认值。合并(c.address1,b.address1,'无地址')。
【解决方案2】:

它返回错误值的原因是您的 case 语句设置为始终返回 arcust 值,因为 THEN & ELSE 的所有部分都引用了指向 arcust 的 b 表别名。在这之间和不正确地比较 null 之间,@ServerSentinel 适当地指出你没有得到你想要的结果。修改您的查询如下指向 c 表别名并将 null 与 IS NULL 进行比较

SELECT DISTINCT a.custno, b.company,
    CASE WHEN c.address1 IS NULL THEN b.address1
    ELSE c.address1
    END as address,
    CASE WHEN c.city IS NULL THEN b.city
    ELSE c.city
    END as city,
    CASE WHEN c.addrstate IS NULL THEN b.addrstate
    ELSE c.addrstate
    END as addrstate,
    CASE WHEN c.zip IS NULL THEN b.zip
    ELSE c.zip
    END as zip,
    invno, descrip, qtyshp, price, extprice, b.tax, invdte 
FROM artran a
LEFT JOIN arcust b ON a.custno = b.custno
LEFT JOIN soaddr c ON a.custno = c.custno

接下来学习 COALESCE() 在这里对你有很大的帮助,因为它基本上会为你编写 case 语句并返回第一个非 null 值。所以你可以简单地写:

SELECT DISTINCT a.custno, b.company,
    COALESCE(c.address1,b.address1) as address,
    COALESCE(c.city,b.city) as city,
    COALESCE(c.addrstate,b.addrstate) as addrstate,
    COALESCE(c.zip,b.zip) as zip,
    invno, descrip, qtyshp, price, extprice, b.tax, invdte 
FROM artran a
LEFT JOIN arcust b ON a.custno = b.custno
LEFT JOIN soaddr c ON a.custno = c.custno

如果 soaddr 列不为空,那么它会为您提供,如果是,那么您将获得 arcust 地址。

但是,由于地址数据可能应该保存在一起,这意味着您应该从 1 个表中选择整个地址,而不是潜在地合并,您应该坚持使用 case 语句,但始终测试 1 个字段以确定是否有一个 soaddr,该字段应该是该表的唯一 ID(如果存在),如果不使用另一列,例如 Address1。

SELECT DISTINCT a.custno, b.company,
    CASE WHEN c.UniqueId IS NULL THEN b.address1
    ELSE c.address1
    END as address,
    CASE WHEN c.UniqueId IS NULL THEN b.city
    ELSE c.city
    END as city,
    CASE WHEN c.UniqueId IS NULL THEN b.addrstate
    ELSE c.addrstate
    END as addrstate,
    CASE WHEN c.UniqueId IS NULL THEN b.zip
    ELSE c.zip
    END as zip,
    invno, descrip, qtyshp, price, extprice, b.tax, invdte 
FROM artran a
LEFT JOIN arcust b ON a.custno = b.custno
LEFT JOIN soaddr c ON a.custno = c.custno

【讨论】:

  • 就是这样!感谢您的帮助!
猜你喜欢
  • 2012-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-02
  • 1970-01-01
  • 2011-03-15
  • 2017-09-07
  • 1970-01-01
相关资源
最近更新 更多