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

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

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.

  1. WITH split_values AS
  2. (SELECT REGEXP_SUBSTR(values_to_split, '[^,]+', 1, level) AS splitted, temp_rowid
  3. FROM (SELECT values_to_split, rowid temp_rowid FROM my_table
  4. WHERE values_to_split IS NOT NULL) temp_table
  5. GROUP BY REGEXP_SUBSTR(values_to_split, '[^,]+', 1, level), temp_rowid
  6. CONNECT BY REGEXP_SUBSTR(values_to_split, '[^,]+', 1, level) IS NOT NULL),
  7. max_value AS
  8. (SELECT MAX(splitted) max_part, temp_rowid FROM split_values
  9. GROUP BY temp_rowid),
  10. binary_zeros AS
  11. (SELECT lpad('0', max_part + 1, '0') zero_binary_seq, temp_rowid from max_value)
  12. SELECT regexp_replace(bz.zero_binary_seq,'.', '1', 2, sv.splitted) FROM binary_zeros bz
  13. 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.

  1. WITH split_values AS
  2. (SELECT REGEXP_SUBSTR(values_to_split, '[^,]+', 1, level) AS splitted, temp_rowid
  3. FROM (SELECT values_to_split, rowid temp_rowid FROM my_table
  4. WHERE values_to_split IS NOT NULL) temp_table
  5. GROUP BY REGEXP_SUBSTR(values_to_split, '[^,]+', 1, level), temp_rowid
  6. CONNECT BY REGEXP_SUBSTR(values_to_split, '[^,]+', 1, level) IS NOT NULL),
  7. max_value AS
  8. (SELECT MAX(splitted) max_part, temp_rowid FROM split_values
  9. GROUP BY temp_rowid),
  10. binary_zeros AS
  11. (SELECT lpad('0', max_part + 1, '0') zero_binary_seq, temp_rowid from max_value)
  12. SELECT regexp_replace(bz.zero_binary_seq,'.','1',2,sv.splitted) FROM binary_zeros bz
  13. 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

以下是翻译好的部分:

  1. 使用递归查询可以将字符串拆分(使用简单的字符串函数而不是缓慢的正则表达式),然后使用算术运算生成二进制数:
  2. WITH recursion (bit_list, epos, bit_value) AS (
  3. SELECT bit_list,
  4. INSTR(bit_list, ',', 1),
  5. CASE
  6. WHEN INSTR(bit_list, ',', 1) = 0
  7. THEN POWER(10, bit_list)
  8. ELSE POWER(10, SUBSTR(bit_list, 1, INSTR(bit_list, ',', 1) - 1))
  9. END
  10. FROM table_name
  11. UNION ALL
  12. SELECT bit_list,
  13. INSTR(bit_list, ',', epos + 1),
  14. bit_value
  15. + CASE
  16. WHEN INSTR(bit_list, ',', epos + 1) = 0
  17. THEN POWER(10, SUBSTR(bit_list, epos + 1))
  18. ELSE POWER(10, SUBSTR(bit_list, epos + 1, INSTR(bit_list, ',', epos + 1) - epos - 1))
  19. END
  20. FROM recursion
  21. WHERE epos > 0
  22. )
  23. SELECT bit_list,
  24. bit_value
  25. FROM recursion
  26. WHERE epos = 0;

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

  1. CREATE TABLE table_name (bit_list) AS
  2. SELECT '1,3,4' FROM DUAL UNION ALL
  3. SELECT '1,6,7' FROM DUAL UNION ALL
  4. SELECT '4,3,1' FROM DUAL UNION ALL
  5. 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:

  1. WITH recursion (bit_list, epos, bit_value) AS (
  2. SELECT bit_list,
  3. INSTR(bit_list, ',', 1),
  4. CASE
  5. WHEN INSTR(bit_list, ',', 1) = 0
  6. THEN POWER(10, bit_list)
  7. ELSE POWER(10, SUBSTR(bit_list, 1, INSTR(bit_list, ',', 1) - 1))
  8. END
  9. FROM table_name
  10. UNION ALL
  11. SELECT bit_list,
  12. INSTR(bit_list, ',', epos + 1),
  13. bit_value
  14. + CASE
  15. WHEN INSTR(bit_list, ',', epos + 1) = 0
  16. THEN POWER(10, SUBSTR(bit_list, epos + 1))
  17. ELSE POWER(10, SUBSTR(bit_list, epos + 1, INSTR(bit_list, ',', epos + 1) - epos - 1))
  18. END
  19. FROM recursion
  20. WHERE epos > 0
  21. )
  22. SELECT bit_list,
  23. bit_value
  24. FROM recursion
  25. WHERE epos = 0;

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

  1. CREATE TABLE table_name (bit_list) AS
  2. SELECT '1,3,4' FROM DUAL UNION ALL
  3. SELECT '1,6,7' FROM DUAL UNION ALL
  4. SELECT '4,3,1' FROM DUAL UNION ALL
  5. 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:

确定