仅当特定值不存在时,SQL 才选择默认值

标签 sql oracle

我正在尝试基于多列连接 2 个表,但如果任何给定列不存在特定值,我想从默认行返回结果。

以下是我尝试加入的 2 个表的示例:

数据表:

 ID      CATEGORY_1          CATEGORY_2         CATEGORY_3
 1           Y                   Y                  Y 
 2           Y                   N                  N 
 3           Y                   N                  Y 

帐户_表:
 CATEGORY_1       CATEGORY_2     CATEGORY_3     ACCT_NUM
     Y                Y              Y            123
     Y                N              ALL          234
     ALL              ALL            Y            345

我想要实现的是,如果数据在 CATEGORY_1、2 和 3 上匹配,则选择 ACCOUNT_TABLE.ACCT_NUM,但如果不匹配,则从 ACCOUNT_TABLE 中选择与“ALL”值关联的 ACCT_NUM。此外,如果由于 ACCOUNT_TABLE 中的“ALL”值而可以找到多个记录,我想根据优先级返回 ACCT_NUM(即,CATEGORY_1 上的匹配优先于 CATEGORY_2 上的匹配)。

到目前为止,我写的查询如下:
 select d.*, a.acct_num from data_table d, account_table a
  where d.category_1 = DECODE(a.category_1,'ALL',d.category_1,a.category_1)
  and d.category_2 = DECODE(a.category_2,'ALL',d.category_2,a.category_2)
  and d.category_3 = DECODE(a.category_3,'ALL',d.category_3,a.category_3)

但我的输出是这样的:
 ID    CATEGORY_1       CATEGORY_2     CATEGORY_3     ACCT_NUM
 1         Y                Y              Y            123
 1         Y                Y              Y            345
 2         Y                N              N            234
 3         Y                N              Y            234
 3         Y                N              Y            345

对于 ID 1,我只希望返回 ACCT_NUM 123,因为类别 1、2 和 3 的匹配应优先于“ALL”记录。

ID 2 正确匹配并返回预期的 ACCT_NUM。

ID 3 我想返回 ACCT_NUM 234,因为类别 1+2 的匹配应该优先于类别 3 的匹配。

所以下面是我的预期输出:
 ID    CATEGORY_1       CATEGORY_2     CATEGORY_3     ACCT_NUM
 1         Y                Y              Y            123
 2         Y                N              N            234
 3         Y                N              Y            234

关于如何编写查询以实现上述目标的任何帮助/建议?

最佳答案

这最好使用相关子查询来完成。在 Oracle 12g 中,您可以执行以下操作:

select d.*,
       (select a.acct_num
        from account_table a
        where (d.category_1 = a.category_1 or a.category_1 = 'ALL') and
              (d.category_2 = a.category_2 or a.category_2 = 'ALL') and
              (d.category_3 = a.category_3 or a.category_3 = 'ALL')
        order by ((case when a.category_1 = 'ALL' then 1 else 0 end) +
                  (case when a.category_2 = 'ALL' then 1 else 0 end) +
                  (case when a.category_3 = 'ALL' then 1 else 0 end)
                 ) asc
        fetch first 1 row only
       ) as acct_num       
from data_table d;

也就是说,获取具有最少“全部”值的匹配项。

在早期版本的 Oracle 中,您可以使用聚合和 keep 做同样的事情。 :
select d.*,
       (select max(a.acct_num) keep (dense_rank first
                                     order by ((case when a.category_1 = 'ALL' then 1 else 0 end) +
                                               (case when a.category_2 = 'ALL' then 1 else 0 end) +
                                               (case when a.category_3 = 'ALL' then 1 else 0 end)
                                              ) asc
                                     )
        from account_table a
        where (d.category_1 = a.category_1 or a.category_1 = 'ALL') and
              (d.category_2 = a.category_2 or a.category_2 = 'ALL') and
              (d.category_3 = a.category_3 or a.category_3 = 'ALL')

       ) as acct_num       
from data_table d;

你也可以用 join 做类似的事情然后使用 row_number()为排名。

关于仅当特定值不存在时,SQL 才选择默认值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31686341/

相关文章:

sql - 将编码信息添加到 FOR XML 的结果中

来自不同来源的 Oracle 过程插入

sql - regexp_like 选择属性字符串包含几个不同单词的行

mysql - 需要有关如何构建在线集换式纸牌游戏的数据库架构的建议

php - 通过循环将 INSERT 追加到 SQL 中

java - 从 JpaRepository native 查询返回字符串?

php - 学说 2 : How to change from MySQL to Oracle database

mysql - 将一张表转换为两张新表

sql - Oracle SQL XMLElement 仅输出 (XMLTYPE)

oracle - 排序是发生在 Oracle 的 DB Buffer 缓存还是 PGA 中?