如何根据出现的次数获取一个值

问题描述 投票:0回答:1

我有一个像这样的键值表:

enter image description here

如何根据key的出现索引获取值。

我只使用了关键索引

select INSTR ( key,
       'key5<>'
      , 1,1
      )
  from table ;

我应该如何获得分隔符出现的补充值?

我想获得“key5”的并行值,即 961。

sql oracle csv
1个回答
0
投票

您的

instr
查询告诉您键的第一个字符在字符串中的位置(即它是第 25 个字符),而不是元素的位置(即它是第五个字符);这根本无法帮助您找到匹配的值,因为它不会从相同的字符位置开始。它还可能会给您带来误报,例如如果“key50”出现在“key5”之前(我猜你的键并不像你所显示的那样真正按顺序排列)。

您可以使用正则表达式来提取所有键和值,并使用递归 CTE(子查询分解)来处理所有键/值对。

with rcte (all_keys, all_values, key_count, pos, key, value) as (
  select key, value, regexp_count(key, '(.*?)(<>|$)'), 1,
    regexp_substr(key, '(.*?)(<>|$)', 1, 1, null, 1),
    regexp_substr(value, '(.*?)(<>|$)', 1, 1, null, 1)
  from your_table
  union all
  select all_keys, all_values, key_count, pos + 1,
    regexp_substr(all_keys, '(.*?)(<>|$)', 1, pos + 1, null, 1),
    regexp_substr(all_values, '(.*?)(<>|$)', 1, pos + 1, null, 1)
  from rcte
  where pos < key_count - 1
)
select pos, key, value from rcte
POS 钥匙 价值
1 键1 300
2 键2 77
3 键3 -15
4 键4 40
5 键5 961
6 键6 1
7 键7 300
8 key8 -1

锚分支获取原始的分隔键和值字符串、键数量的计数,并通过查找与正则表达式模式匹配的第一个值来开始工作。然后递归分支查找连续的匹配项,直到所有键都用完。

然后只需过滤您需要的键值即可:

with rcte (all_keys, all_values, key_count, pos, key, value) as (
  select key, value, regexp_count(key, '(.*?)(<>|$)'), 1,
    regexp_substr(key, '(.*?)(<>|$)', 1, 1, null, 1),
    regexp_substr(value, '(.*?)(<>|$)', 1, 1, null, 1)
  from your_table
  union all
  select all_keys, all_values, key_count, pos + 1,
    regexp_substr(all_keys, '(.*?)(<>|$)', 1, pos + 1, null, 1),
    regexp_substr(all_values, '(.*?)(<>|$)', 1, pos + 1, null, 1)
  from rcte
  where pos < key_count - 1
)
select value
from rcte
where key = 'key5'
价值
961

小提琴


如果您的键的最大数量较小,您也可以使用 case 表达式,并为每个可能的位置匹配 when/then 子句,但这会更难维护,并且可能会表现更差 - 但只是为了好玩,这个小提琴展示了这种方法。

无论哪种方式,必须这样做都说明了为什么在字符串中存储分隔数据不是一个好主意;最好首先将其关联存储。

© www.soinside.com 2019 - 2024. All rights reserved.