oracle 基于优先级从同一个表中获取两个最上面的记录,查询几乎相同(使用通配符)

pw136qt2  于 2023-08-04  发布在  Oracle
关注(0)|答案(2)|浏览(117)

我正在使用以下查询:

select AAA, BBB, CCC, DDD from (
select * from TABLE_A
where (AAA='a1' or AAA='*')
and (BBB='b1' or BBB='*')
and (CCC='c1' or CCC='*')
and (DDD='false')
order by decode(AAA, '*', 0, 4) + decode(BBB, '*', 0, 2) + decode(CCC, '*', 0, 1) desc
)where rownum <= 1

字符串
获取DDD=false的顶级记录(基于优先级,带通配符)。优先级只适用于我有一个完全匹配,通配符匹配它被忽略(AAA>BBB>CCC)。我想得到第二条记录,但是DDD=true,并将它们合并,这样我总共得到2条记录(最上面的一条DDD=false,最上面的一条DDD=true):
我试过只添加UNION ALL和查询的副本,同时更改DDD='true',但它看起来并不理想,因为它基本上复制了完整的查询,只有DDD='true'与第一个查询不同:

select AAA, BBB, CCC, DDD from (
select * from TABLE_A
where (AAA='a1' or AAA='*')
and (BBB='b1' or BBB='*')
and (CCC='c1' or CCC='*')
and (DDD='false')
order by decode(AAA, '*', 0, 4) + decode(BBB, '*', 0, 2) + decode(CCC, '*', 0, 1) desc
)where rownum <= 1

UNION ALL
select AAA, BBB, CCC, DDD from (
select * from TABLE_A
where (AAA='a1' or AAA='*')
and (BBB='b1' or BBB='*')
and (CCC='c1' or CCC='*')
and (DDD='true')
order by decode(AAA, '*', 0, 4) + decode(BBB, '*', 0, 2) + decode(CCC, '*', 0, 1) desc
)where rownum <= 1


有没有更聪明的方法来实现这一点?

k97glaaz

k97glaaz1#

在DDD上使用RANKDENSE_RANKROW_NUMBER分区:

select AAA, BBB, CCC, DDD
  from (select AAA, BBB, CCC, DDD,
               RANK() OVER (PARTITION BY DDD 
                            ORDER BY DECODE(AAA,'*',1,0), 
                                     DECODE(BBB,'*',1,0), 
                                     DECODE(CCC,'*',1,0)) rnk
          from TABLE_A
         where (AAA='a1' or AAA='*')
           and (BBB='b1' or BBB='*')
           and (CCC='c1' or CCC='*'))
 where rnk = 1

字符串
如果您有任何具有相同秩的行,则可能返回2个以上的结果。如果在这种情况下只需要一个,请将RANK()更改为ROW_NUMBER()

h4cxqtbf

h4cxqtbf2#

您可以使用IN来简化过滤条件,并确保您只获得DDDtruefalse值,然后使用ROW_NUMBER解析函数来模拟多个分区的ROWNUM伪列行为:

select AAA, BBB, CCC, DDD
from (
  select aaa,
         bbb,
         ccc,
         ddd,
         ROW_NUMBER() OVER (
           PARTITION BY ddd
           ORDER BY DECODE(aaa, '*', 0, 4)
                  + DECODE(bbb, '*', 0, 2)
                  + DECODE(ccc, '*', 0, 1) DESC
         ) AS rn
  from   TABLE_A
  where  AAA IN ('a1', '*')
  and    BBB IN ('b1', '*')
  and    CCC IN ('c1', '*')
  and    DDD IN ('true', 'false')
)
where  rn = 1;

字符串

相关问题