我有一个唯一的字符串列表(最初的想法是表中的列名).
任务是执行列表的最大可能缩写,因此列表保持不同.
任务是执行列表的最大可能缩写,因此列表保持不同.
例如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解决方案.其他RDBMS的首选Oracle解决方案受到欢迎.
解决方法
我会在递归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,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
Here是db<>小提琴.
严格来说,没有必要.您可以按顺序使用length(abbr)desc.但是,当我使用递归CTE时,我通常会包含一个递归计数器,所以这就是习惯.
在CTE中进行额外的比较可能看起来更复杂,但它简化了执行 – 递归停止在正确的值.
这也是在唯一的单字母col值上测试的.