如何在Oracle SQL中将带有分隔符的数字序列转换为二进制?

huangapple go评论56阅读模式
英文:

How to convert number sequence with delimiter into binary in Oracle SQL?

问题

I have to parse sequences like '1,3,4', '1,6,7' and convert them to binary numbers (bit is set for existed value, otherwise - 0).
For instance, there is a sequence '1,3,5'. It needs to convert it into binary 101010.

Now I have a query but I got stuck on the stage when it needs to set bits correctly. I mean, I got separate row bit for every decimal value.

WITH split_values AS
(SELECT REGEXP_SUBSTR(values_to_split, '[^,]+', 1, level) AS splitted, temp_rowid
FROM (SELECT values_to_split, rowid temp_rowid FROM my_table
      WHERE values_to_split IS NOT NULL) temp_table
  GROUP BY REGEXP_SUBSTR(values_to_split, '[^,]+', 1, level), temp_rowid
  CONNECT BY REGEXP_SUBSTR(values_to_split, '[^,]+', 1, level) IS NOT NULL),
max_value AS
(SELECT MAX(splitted) max_part, temp_rowid FROM split_values
GROUP BY temp_rowid),
binary_zeros AS
(SELECT lpad('0', max_part + 1, '0') zero_binary_seq, temp_rowid from max_value)
SELECT regexp_replace(bz.zero_binary_seq,'.', '1', 2, sv.splitted) FROM binary_zeros bz
JOIN split_values sv ON sv.temp_rowid = bz.temp_rowid;

Values to split placed in values_to_split column in my_table

英文:

I have to parse sequences like '1,3,4', '1,6,7' and convert them to binary numbers (bit is set for existed value, otherwise - 0).
For instance, there is a sequence '1,3,5'. It needs to convert it into binary 101010.

Now I have a query but I got stuck on the stage when it needs to set bits correctly. I mean, I got separate row bit for every decimal value.

WITH split_values AS
(SELECT REGEXP_SUBSTR(values_to_split, '[^,]+', 1, level) AS splitted, temp_rowid
FROM (SELECT values_to_split, rowid temp_rowid FROM my_table
      WHERE values_to_split IS NOT NULL) temp_table
  GROUP BY REGEXP_SUBSTR(values_to_split, '[^,]+', 1, level), temp_rowid
  CONNECT BY REGEXP_SUBSTR(values_to_split, '[^,]+', 1, level) IS NOT NULL),
max_value AS
(SELECT MAX(splitted) max_part, temp_rowid FROM split_values
GROUP BY temp_rowid),
binary_zeros AS
(SELECT lpad('0', max_part + 1, '0') zero_binary_seq, temp_rowid from max_value)
SELECT regexp_replace(bz.zero_binary_seq,'.','1',2,sv.splitted) FROM binary_zeros bz
JOIN split_values sv ON sv.temp_rowid = bz.temp_rowid;

Values to split placed in values_to_split column in my_table

答案1

得分: 1

以下是翻译好的部分:

使用递归查询可以将字符串拆分(使用简单的字符串函数而不是缓慢的正则表达式),然后使用算术运算生成二进制数:

WITH recursion (bit_list, epos, bit_value) AS (
  SELECT bit_list,
         INSTR(bit_list, ',', 1),
         CASE
         WHEN INSTR(bit_list, ',', 1) = 0
         THEN POWER(10, bit_list)
         ELSE POWER(10, SUBSTR(bit_list, 1, INSTR(bit_list, ',', 1) - 1))
         END
  FROM   table_name
UNION ALL
  SELECT bit_list,
         INSTR(bit_list, ',', epos + 1),
         bit_value
         + CASE
           WHEN INSTR(bit_list, ',', epos + 1) = 0
           THEN POWER(10, SUBSTR(bit_list, epos + 1))
           ELSE POWER(10, SUBSTR(bit_list, epos + 1, INSTR(bit_list, ',', epos + 1) - epos - 1))
           END
  FROM   recursion
  WHERE  epos > 0
)
SELECT bit_list,
       bit_value
FROM   recursion
WHERE  epos = 0;

对于示例数据(假定列表中永远不会有重复项):

CREATE TABLE table_name (bit_list) AS
SELECT '1,3,4' FROM DUAL UNION ALL
SELECT '1,6,7' FROM DUAL UNION ALL
SELECT '4,3,1' FROM DUAL UNION ALL
SELECT '0,1,2,3,4,5,6,7' FROM DUAL;

输出:

BIT_LIST BIT_VALUE
1,3,4 11010
1,6,7 11000010
4,3,1 11010
0,1,2,3,4,5,6,7 11111111

fiddle

英文:

You can use a recursive query to split the string (using simple string functions rather than slow regular expressions) and then use arithmetic to generate the binary number:

WITH recursion (bit_list, epos, bit_value) AS (
  SELECT bit_list,
         INSTR(bit_list, ',', 1),
         CASE
         WHEN INSTR(bit_list, ',', 1) = 0
         THEN POWER(10, bit_list)
         ELSE POWER(10, SUBSTR(bit_list, 1, INSTR(bit_list, ',', 1) - 1))
         END
  FROM   table_name
UNION ALL
  SELECT bit_list,
         INSTR(bit_list, ',', epos + 1),
         bit_value
         + CASE
           WHEN INSTR(bit_list, ',', epos + 1) = 0
           THEN POWER(10, SUBSTR(bit_list, epos + 1))
           ELSE POWER(10, SUBSTR(bit_list, epos + 1, INSTR(bit_list, ',', epos + 1) - epos - 1))
           END
  FROM   recursion
  WHERE  epos > 0
)
SELECT bit_list,
       bit_value
FROM   recursion
WHERE  epos = 0;

Which, for the sample data (which assumes that you will never have duplicate items in the list):

CREATE TABLE table_name (bit_list) AS
SELECT '1,3,4' FROM DUAL UNION ALL
SELECT '1,6,7' FROM DUAL UNION ALL
SELECT '4,3,1' FROM DUAL UNION ALL
SELECT '0,1,2,3,4,5,6,7' FROM DUAL;

Outputs:

BIT_LIST BIT_VALUE
1,3,4 11010
1,6,7 11000010
4,3,1 11010
0,1,2,3,4,5,6,7 11111111

fiddle

huangapple
  • 本文由 发表于 2023年6月8日 19:56:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76431617.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定