oracle:你能跨表使用DECODE吗?

时间:2011-02-07 00:25:42

标签: sql oracle decode

这个函数很新,但据我所知,DECODE测试指定属性(arg1)对另一个指定值(arg2)并且如果它们匹配,则显示结果(arg3)否则如果它不匹配,则默认将显示(arg4)

DECODE(firstname,'John','last is doe','I don't know the last name')

您可以使用其他表中的数据来模拟联接吗?像

DECODE(publisherid, publisher.pubid, publisher.name,'unknown')

我正在尝试但它无法正常工作。不知道是否有可能或者我只是做错了。有什么想法吗?

4 个答案:

答案 0 :(得分:4)

11g documentation表示搜索参数可以是表达式,因此您应该使用的是什么。如果您收到ORA错误,请告知我们。否则,您可能没有匹配的数据,或者publisher.name列为空...

您不会使用它来模拟连接 - 您仍然希望实际上JOIN(ANSI 89或92语法,但最好是92)表格,或者您将处理来自笛卡尔的大量垃圾行然后DECODE将执行的产品。

除非您使用9i之前的版本(8.1.6, according to Ask Tom),否则我不会浪费您的时间使用DECODE并使用ANSI CASE语句:

CASE 
  WHEN publisherid = publisher.pubid THEN publisher.name
  ELSE 'unknown'
END

答案 1 :(得分:2)

您可以在不同表的列之间使用它,如下所示:

select oi.order_id, oi.product_id, oi.unit_price, p.list_price, 
       decode(oi.unit_price, p.list_price, 'No Discount',
                   p.list_price - oi.unit_price||' discount') disc
from demo_ord_items oi 
  join demo_product_info p on p.product_id = oi.product_id
where oi.order_id = 1

理论上,您可以将其用作连接条件

select oi.order_id, oi.product_id, oi.unit_price, p.list_price
from demo_ord_items oi 
  join demo_product_info p on p.product_id = oi.product_id 
                            and decode(oi.unit_price, p.list_price,0,1) = 1
where oi.order_id = 1

但这并不常见。条件是布尔值(true / false),并且解码返回一个数字或字符,因此解码有点冗余(或者可能重写为更清晰)。

答案 2 :(得分:0)

就语法而言,你得到了正确的答案。如果你总是得到'未知',结果输出你的发布者并检查你是否在表中。

如果ID-s是文本字段,请注意解码区分大小写。还要检查你是否在某处修剪了ids。

答案 3 :(得分:0)

如果满足以下任何条件,请使用DECODE

  • 您想编写非可移植SQL
  • 您希望编写只有Oracle开发人员能够识别和理解的代码
  • 您想编写难以阅读的代码
  • 您希望在下次更改代码时增加引入错误的机会
  • 您希望优化器生成次优的执行计划(在where子句中使用时)。
  • 您正在编写丢弃代码

简而言之,根本不要使用DECODE。用CASE/WHEN无法完成任何事情。是的,键盘会有更多的打字,而且“值得”它。

话虽如此,当我总是喜欢DECODE时,有一个丢失的案例,这与它处理NULL的方式有关。这个场景是我有两个(希望)相同的表具有相同的键,当我想知道是否有任何行,其中两个表不同意列值。

例如,假设您出于性能原因重写了批处理过程,并且您希望确保新版本产生与旧版本相同的结果。在这种情况下,您会将NULLNULL视为相同的“值”。 DECODE碰巧表现得像那样。

decode(a, b, 'Y', 'N') 

将转换为以下情况/当构造

case when a = b then 'Y'
     when a is null and b is null then 'Y'
     else 'N'
 end  

这是我的意思的一个例子

with old_table as(
  select 1 as id, 'A'  as old_col from dual union all
  select 2 as id, 'A'  as old_col from dual union all
  select 3 as id, 'A'  as old_col from dual union all
  select 4 as id, null as old_col from dual
)
,new_table as(
  select 1 as id, 'A'   as new_col from dual union all
  select 2 as id, 'B'   as new_col from dual union all
  select 3 as id, null  as new_col from dual union all
  select 4 as id, null  as new_col from dual
)
select id
      ,old_col
      ,new_col
      ,decode(old_col, new_col, 'Y', 'N') as has_same_val
  from old_table 
  join new_table using(id);

ID OLD_COL NEW_COL HAS_SAME_VAL
-- ------- ------- ------------
 1 A       A       Y
 2 A       B       N
 3 A       null    N            <-- Note those
 4 null    null    Y            <-- two cases

所以要找到我会做的差异:

where decode(old_col1, new_col1, 'same', 'diff') = 'diff'
   or decode(old_col2, new_col2, 'same', 'diff') = 'diff'
   or decode(old_col3, new_col3, 'same', 'diff') = 'diff'
   or decode(old_col4, new_col4, 'same', 'diff') = 'diff'
   or decode(old_col5, new_col5, 'same', 'diff') = 'diff'