I have a database table (Oracle 11g) of the questionnaire feedback, including multiple selection, several answer questions. The Options column has every value that the user can select, and the Answers column has numerical values ββfor what they selected.
ID_NO OPTIONS ANSWERS 1001 Apple Pie|Banana-Split|Cream Tea 1|2 1002 Apple Pie|Banana-Split|Cream Tea 2|3 1003 Apple Pie|Banana-Split|Cream Tea 1|2|3
I need a query that will decode the answers, and text versions of the answers as one line.
ID_NO ANSWERS ANSWER_DECODE 1001 1|2 Apple Pie|Banana-Split 1002 2|3 Banana-Split|Cream Tea 1003 1|2|3 Apple Pie|Banana-Split|Cream Tea
I experimented with regular expressions to replace values ββand get substrings, but I cannot develop a way to merge the two correctly.
WITH feedback AS ( SELECT 1001 id_no, 'Apple Pie|Banana-Split|Cream Tea' options, '1|2' answers FROM DUAL UNION SELECT 1002 id_no, 'Apple Pie|Banana-Split|Cream Tea' options, '2|3' answers FROM DUAL UNION SELECT 1003 id_no, 'Apple Pie|Banana-Split|Cream Tea' options, '1|2|3' answers FROM DUAL ) SELECT id_no, options, REGEXP_SUBSTR(options||'|', '(.)+?\|', 1, 2) second_option, answers, REGEXP_REPLACE(answers, '(\d)+', ' \1 ') answer_numbers, REGEXP_REPLACE(answers, '(\d)+', REGEXP_SUBSTR(options||'|', '(.)+?\|', 1, To_Number('2'))) "???" FROM feedback
I do not want to manually define or decode responses in SQL; There are many polls with different questions (and a different number of options), so I hope there will be a solution that will work dynamically for all of them.
I tried to split the parameters and responses into separate lines using LEVEL and reattach them to the codes, but this works very slowly with the actual data set (5-option question with 600 rows of answers).
WITH feedback AS ( SELECT 1001 id_no, 'Apple Pie|Banana-Split|Cream Tea' options, '1|2' answers FROM DUAL UNION SELECT 1002 id_no, 'Apple Pie|Banana-Split|Cream Tea' options, '2|3' answers FROM DUAL UNION SELECT 1003 id_no, 'Apple Pie|Banana-Split|Cream Tea' options, '1|2|3' answers FROM DUAL ) SELECT answer_rows.id_no, ListAgg(option_rows.answer) WITHIN GROUP(ORDER BY option_rows.lvl) FROM (SELECT DISTINCT LEVEL lvl, REGEXP_SUBSTR(options||'|', '(.)+?\|', 1, LEVEL) answer FROM (SELECT DISTINCT options, REGEXP_COUNT(options||'|', '(.)+?\|') num_choices FROM feedback) CONNECT BY LEVEL <= num_choices ) option_rows LEFT OUTER JOIN (SELECT DISTINCT id_no, to_number(REGEXP_SUBSTR(answers, '(\d)+', 1, LEVEL)) answer FROM (SELECT DISTINCT id_no, answers, To_Number(REGEXP_SUBSTR(answers, '(\d)+$')) max_answer FROM feedback) WHERE to_number(REGEXP_SUBSTR(answers, '(\d)+', 1, LEVEL)) IS NOT NULL CONNECT BY LEVEL <= max_answer ) answer_rows ON option_rows.lvl = answer_rows.answer GROUP BY answer_rows.id_no ORDER BY answer_rows.id_no
If there is no solution using Regex, is there a better way than LEVEL to separate the values? Or is there another approach that will work?