通过 Oracle SQL 返回输入字符串中出现的最大字符

Posted

技术标签:

【中文标题】通过 Oracle SQL 返回输入字符串中出现的最大字符【英文标题】:Return maximum occurring character in an input string though Oracle SQL 【发布时间】:2021-12-29 10:53:44 【问题描述】:

如果我有水果名称,如木瓜、橙子等,请逐行说明...

如何找到每个字符串中出现的最大字符。 对于木瓜,它将是“a”,因为它重复了 3 次 对于橙色,它将是所有字符,因为每个字符只重复一次 我需要使用 Oracle SQL 解决上述查询

【问题讨论】:

这能回答你的问题吗? How to count the number of occurrences of a character in an Oracle varchar value? 不..我需要找到字符的最大出现次数。在那个问题中,事先提到要找到特定字符的字符总数。但在这个问题中,我需要找到包含最多时间的字符 【参考方案1】:

这是一种选择:

SQL> WITH
  2     fruit (name)
  3     AS
  4        (SELECT 'Papaya' FROM DUAL
  5         UNION ALL
  6         SELECT 'Orange' FROM DUAL),

  7     temp
  8     AS
  9        (SELECT name, SUBSTR (name, COLUMN_VALUE, 1) letter
 10           FROM fruit
 11                CROSS JOIN
 12                TABLE (
 13                   CAST (
 14                      MULTISET (    SELECT LEVEL
 15                                      FROM DUAL
 16                                CONNECT BY LEVEL <= LENGTH (name))
 17                         AS SYS.odcinumberlist))),
 18     temp2
 19     AS
 20        (  SELECT name,
 21                  letter,
 22                  COUNT (*) cnt,
 23                  RANK () OVER (PARTITION BY name ORDER BY COUNT (*) DESC) rnk
 24             FROM temp
 25         GROUP BY name, letter)
 26    SELECT name,
 27           LISTAGG (letter, ', ') WITHIN GROUP (ORDER BY letter) letters,
 28           cnt
 29      FROM temp2
 30     WHERE rnk = 1
 31  GROUP BY name, cnt;

NAME   LETTERS                     CNT
------ -------------------- ----------
Orange O, a, e, g, n, r              1
Papaya a                             3

SQL>
TEMPCTE 将名称拆分为行(按每个字母) TEMP2 按数量降序排列 final select 返回排名“最高”的字母

【讨论】:

谢谢伙计!!有没有其他方法可以用不同的方法解决这个查询? 不客气。像往常一样,同样的问题可以用不同的方式解决。我建议了我认为最合适的一个。我想不出比这更好的了。【参考方案2】:

我有另一个想法。

当数据如下。

create table t as 
  select 'Papaya' w from dual union all
  select 'Orange' w from dual union all
  select 'Baby' w from dual union all
  select 'CocaCola' w from dual

获取字母表的最大出现次数并计数如下

with cte as (
  select w, az.c find, regexp_count(w, az.c, 1, 'i') cnt
  from   t,
         (select chr(rownum + 96) c
          from   dual
          connect by rownum <= 26
         ) az
),
cte2 as (
  select w, max(lpad(cnt, 10, '0') || find) cnt_find
  from   cte
  group by w
)
select w, substr(cnt_find, 11, 999) find, to_number(substr(cnt_find, 1, 10)) cnt
from   cte2

结果:

| W        | FIND | CNT |
|----------|------|----:|
| Orange   | r    |   1 |
| Papaya   | a    |   3 |
| Baby     | b    |   2 |
| CocaCola | c    |   3 |

由于字母集限制为 26 种,我生成了 26 行与单词表交叉连接。

select chr(rownum + 96) c
from   dual
connect by rownum <= 26

并使用 regexp_count 获取每个字母的出现次数。

select w, az.c find, regexp_count(w, az.c, 1, 'i') cnt

并检索最大出现次数,然后是按单词分组的字母表。 (lpad 用于填充 10 长度以供所有出现使用 substr 下一步)

select w, max(lpad(cnt, 10, '0') || find) cnt_find
from   cte
group by w

并划分出现次数和字母的最大值。 (substr 是 1 到 10,而 11 到 end,因为所有最大出现的长度都是 10)

select w, substr(cnt_find, 11, 999) find, to_number(substr(cnt_find, 1, 10)) cnt
from   cte2

此链接详细显示了我是如何进行此查询的。

https://dbfiddle.uk/?rdbms=oracle_18&fiddle=29516e70a1270c4035d7165832905777


显示所有获胜者而不是第一个获胜者

with cte as (
  select w, az.c find, regexp_count(w, az.c, 1, 'i') cnt
  from   t,
         (select chr(rownum + 96) c
          from   dual
          connect by rownum <= 26
         ) az
), rank_t as 
(
  select w, find, cnt,
         rank() over (partition by w order by cnt desc) rank_cnt
  from   cte
)
select w,
       listagg(find, ', ') within group (order by w) find_list,
       max(cnt) max_cnt
from   rank_t
where  rank_cnt = 1
group by w

结果:

| W        | FIND_LIST        | MAX_CNT |
|----------|------------------|--------:|
| Baby     | b                |       2 |
| CocaCola | c                |       3 |
| Orange   | a, e, g, n, o, r |       1 |
| Papaya   | a                |       3 |

以前的版本只显示最大的一个最大出现次数。所以我使用 rank 函数将所有最大出现次数设为 1

select w, find, cnt,
       rank() over (partition by w order by cnt desc) rank_cnt
from   cte

只过滤数字 1 并将行转换为带有 listagg 的列

select w,
       listagg(find, ', ') within group (order by w) find_list,
       max(cnt) max_cnt
from   rank_t
where  rank_cnt = 1
group by w

第二个链接详细显示了我是如何进行此查询的。

https://dbfiddle.uk/?rdbms=oracle_18&fiddle=c0c15ccb9974d0c4fd14a34408f69fb7

【讨论】:

嘿伙计...感谢您的解决方案。它也可以正常工作,但是说当存在诸如“橙色”之类的字符串并且所有字符都是唯一的时,第二列仅返回一个字符而不是所有字符,因为所有字符的最大出现次数为 1 个值。然后,您提供的数据也将按预期工作。再次感谢!!! @SSaha 你说得对,我附加了“橙色”大小写。

以上是关于通过 Oracle SQL 返回输入字符串中出现的最大字符的主要内容,如果未能解决你的问题,请参考以下文章

在 Oracle PLSQL 函数的输出过程中出现逗号问题

oracle在sql中判断字段值是数字还是字符串

Oracle保存带&的数据

oracle-游标-存储过程-函数-包

Oracle函数

ORACLE 存储函数