Mar*_*ber 6 sql oracle r distinct-values
我有一个唯一的字符串列表(最初的想法是表中的列名).任务是执行列表的最大可能缩写,因此列表保持不同.
例如AAA, AB可以缩写为AA, AB.(但不是A, AB- A可能是两者的前缀AAA和AB).
AAAA, BAAAA可以缩短到A, B.但A1, A2根本不能缩写.
以下是示例数据
create table tab as 
select 'AAA' col from dual union all
select 'AABA' col from dual union all
select 'COL1' col from dual union all
select 'COL21' col from dual union all
select 'AAAAAA' col from dual union all
select 'BBAA' col from dual union all
select 'BAAAA' col from dual union all
select 'AB' col from dual;
预期的结果是
COL    ABR_COL                
------ ------------------------
AAA    AAA                      
AAAAAA AAAA                     
AABA   AAB                      
AB     AB                       
BAAAA  BA                       
BBAA   BB                       
COL1   COL1                     
COL21  COL2        
我管理了一个由四个子查询组成的强力解决方案,我没有故意发布,因为我希望有一个更简单的解决方案,我不想分散注意力.
顺便说一句,在r调用中有一个类似的函数abbreviate,但我正在寻找SQL解决方案.首选Oracle为其他RDBMS解决方案welcommed.
我会在递归 CTE 中进行过滤:
with potential_abbreviations(col, abbr, lev) as (
      select col, col as abbr, 1 as lev
      from tab
      union all
      select pa.col, substr(pa.abbr, 1, length(pa.abbr) - 1) as abbr, lev + 1
      from potential_abbreviations pa
      where length(abbr) > 1 and
            not exists (select 1
                        from tab
                        where tab.col like substr(pa.abbr, 1, length(pa.abbr) - 1) || '%' and
                              tab.col <> pa.col
                       )
     )
select pa.col, pa.abbr
from (select pa.*, row_number() over (partition by pa.col order by pa.lev desc) as seqnum
      from potential_abbreviations pa
     ) pa
where seqnum = 1
这是一个 db<>fiddle。
这lev是完全没有必要的。您可以length(abbr) desc在order by. 但是,当我使用递归 CTE 时,我通常会包含一个递归计数器,所以这是习惯。
在 CTE 中进行额外的比较可能看起来更复杂,但它简化了执行——递归在正确的值处停止。
这也针对唯一的单字母col值进行了测试。