Mam tabelę bazy danych (Oracle 11g) z opinii na temat kwestionariusza, w tym pytania wielokrotnego wyboru i odpowiedzi wielokrotnej. W kolumnie Opcje znajduje się każda wartość, którą użytkownik może wybrać, a kolumna Odpowiedzi zawiera wartości liczbowe wybranych przez siebie.Regex SQL - Zamień na podciąg z innego pola
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
Potrzebuję kwerendę, która dekoduje odpowiedzi, ze tresc odpowiedzi jako jeden ciąg.
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 eksperymentowali z wyrażeń regularnych, aby zastąpić wartości i dostać podciągi, ale nie mogę wypracować sposób, aby poprawnie połączy dwa.
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
Nie chcę ręcznie definiować ani dekodować odpowiedzi w SQL; istnieje wiele ankiet z różnymi pytaniami (i różnymi liczbami opcji), więc mam nadzieję, że istnieje rozwiązanie, które będzie dynamicznie działać dla nich wszystkich.
Próbowałem podzielić opcje i odpowiedzi na osobne wiersze według POZIOMU, i ponownie dołączyć je tam, gdzie kody pasują, ale to działa bardzo wolno z rzeczywistego zestawu danych (pytanie 5 opcji z 600 rzędów odpowiedzi).
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
Jeśli nie jest to rozwiązanie tylko przy użyciu regex, czy jest bardziej efektywny sposób niż poziom podziału wartości? Czy istnieje inne podejście, które mogłoby zadziałać?
Stosowna: http://stackoverflow.com/questions/26407538/split-string-into-rows-oracle-sql – QuestionC
Dlaczego nie funkcja. Powinien być prostszy. –