保持唯一的字符串的缩写

Mar*_*ber 6 sql oracle r distinct-values

我有一个唯一的字符串列表(最初的想法是表中的列名).任务是执行列表的最大可能缩写,因此列表保持不同.

例如AAA, AB可以缩写为AA, AB.(但不是A, AB- A可能是两者的前缀AAAAB). 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;
Run Code Online (Sandbox Code Playgroud)

预期的结果是

COL    ABR_COL                
------ ------------------------
AAA    AAA                      
AAAAAA AAAA                     
AABA   AAB                      
AB     AB                       
BAAAA  BA                       
BBAA   BB                       
COL1   COL1                     
COL21  COL2        
Run Code Online (Sandbox Code Playgroud)

我管理了一个由四个子查询组成的强力解决方案,我没有故意发布,因为我希望有一个更简单的解决方案,我不想分散注意力.

顺便说一句,在r调用中有一个类似的函数abbreviate,但我正在寻找SQL解决方案.首选Oracle为其他RDBMS解决方案welcommed.

Gor*_*off 3

我会在递归 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
Run Code Online (Sandbox Code Playgroud)

是一个 db<>fiddle。

lev是完全没有必要的。您可以length(abbr) descorder by. 但是,当我使用递归 CTE 时,我通常会包含一个递归计数器,所以这是习惯。

在 CTE 中进行额外的比较可能看起来更复杂,但它简化了执行——递归在正确的值处停止。

这也针对唯一的单字母col值进行了测试。