英文:
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 |
英文:
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 |
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论