Преобразовать значения строк в столбцы - oracle 11g - PullRequest
0 голосов
/ 29 января 2020

Я извлекаю некоторые данные из полей типа XML, получаю некоторые значения из указанных тегов c, и мне удалось собрать их в виде таких результатов:

echo  | type| color             | active
-------------------------------------------
echo1 | car | yellow,green,blue | no,no,no
echo1 | car | yellow,green      | yes,yes
echo2 | car | green,blue,red    | no,no,no
echo2 | car | blue,red          | yes,yes
echo3 | car | yellow,green      | no,yes
...

Сейчас Мне нужно преобразовать эти результаты в следующее:

echo  | type| color  | active
------------------------------
echo1 | car | yellow | no
echo1 | car | green  | no
echo1 | car | blue   | no
echo1 | car | yellow | yes
echo1 | car | green  | yes
echo2 | car | green  | no
echo2 | car | blue   | no
echo2 | car | red    | no
echo2 | car | blue   | yes
echo2 | car | red    | yes
echo3 | car | yellow | no
echo3 | car | green  | yes
...

, то есть мне нужно разделить значения из 3-го и 4-го столбцов одновременно. Каждое из значений из цветного столбца имеет соответствующее значение в активном столбце, и мне нужно сопоставить эти пары в записях.

Поэтому, имея такие результаты, я использую это:

SELECT  echo, type, trim(x.COLUMN_VALUE) color, trim(y.COLUMN_VALUE) active 
FROM 
( RESULTS )
, xmltable(('"' || REPLACE(color, ',', '","') || '"')) x, xmltable(('"' || REPLACE(active, ',', '","') || '"')) y

ORDER BY echo, type, color, active

Это работает правильно, если я преобразую только один из этих двух столбцов одновременно, но когда я хочу преобразовать 2 сразу, он умножает записи, как если бы умножил значения из столбца y на значения из столбца x.

Если в В последнем столбце были только значения «да» или только «нет», тогда будет работать использование отличных в выборе, это исключит устаревшие (не истинные) записи. Но со смешанными значениями я изо всех сил пытаюсь это сделать.

Может кто-нибудь дать мне совет, как это исправить, чтобы не получать устаревшие записи?

Заранее спасибо!


Образец XML:

<rowCollection>
  <row>
    <column name="active">YES</column>
    <column name="customertype">Default</column>
    <column name="type">Default</column>
    <column name="risklevel">Default</column>
    <column name="color">yellow</column>
  </row>
  <row>
    <column name="active">YES</column>
    <column name="customertype">Default</column>
    <column name="type">Default</column>
    <column name="risklevel">Default</column>
    <column name="color">green</column>
  </row>
</rowCollection>

Фрагмент запроса, используемого для получения результатов:

xmlcast(
  xmlquery(
    'string-join(/rowCollection/row/column[5]/text(),",")'
    passing xml_field
    RETURNING CONTENT
  ) AS VARCHAR2(500)
) color,
xmlcast(
  xmlquery(
    'string-join(/rowCollection/row/column[1]/text(),",")'
    passing xml_field
    RETURNING CONTENT
  ) AS VARCHAR2(300)
) active

Ответы [ 2 ]

0 голосов
/ 29 января 2020

Вы можете использовать hierarchy запрос следующим образом:

SQL> SELECT ECHO, TYPE,
  2      REGEXP_SUBSTR(COLOR, '[^,]+', 1, COLUMN_VALUE) AS COLOR,
  3      REGEXP_SUBSTR(ACTIVE, '[^,]+', 1, COLUMN_VALUE) AS ACTIVE
  4  FROM RESULTS
  5      CROSS JOIN TABLE ( CAST(MULTISET(
  6          SELECT LEVEL FROM DUAL
  7          CONNECT BY LEVEL <= REGEXP_COUNT(COLOR, ',') + 1
  8      ) AS SYS.ODCINUMBERLIST) );

ECHO  TYP COLOR      ACTIVE
----- --- ---------- --------------------------------
echo1 car yellow     no
echo1 car green      no
echo1 car blue       no
echo1 car yellow     yes
echo1 car green      yes
echo2 car green      no
echo2 car blue       no
echo2 car red        no
echo2 car blue       yes
echo2 car red        yes
echo3 car yellow     no
echo3 car green      yes

12 rows selected.

SQL>

Cheers !!

0 голосов
/ 29 января 2020

Используйте рекурсивное условие факторинга подзапроса и используйте INSTR, чтобы итеративно найти разделители, а затем SUBSTR, чтобы извлечь значения:

Oracle Настройка :

CREATE TABLE results ( echo, type, color, active ) AS
SELECT 'echo1', 'car', 'yellow,green,blue', 'no,no,no' FROM DUAL UNION ALL
SELECT 'echo1', 'car', 'yellow,green',      'yes,yes'  FROM DUAL UNION ALL
SELECT 'echo2', 'car', 'green,blue,red',    'no,no,no' FROM DUAL UNION ALL
SELECT 'echo2', 'car', 'blue,red',          'yes,yes'  FROM DUAL UNION ALL
SELECT 'echo3', 'car', 'yellow,green',      'no,yes'   FROM DUAL;

Запрос :

WITH lines ( echo, type, rn, idx, color, active, c_start, c_end, a_start, a_end ) AS (
  SELECT echo,
         type,
         ROW_NUMBER() OVER ( ORDER BY echo, type, color, active ),
         1,
         color,
         active,
         1,
         INSTR(color,',',1),
         1,
         INSTR(active,',',1)
  FROM   results
UNION ALL
  SELECT echo,
         type,
         rn,
         idx + 1,
         color,
         active,
         c_end + 1,
         INSTR(color,',',c_end + 1),
         a_end + 1,
         INSTR(active,',',a_end + 1)
  FROM   lines
  WHERE  c_end > 0
  AND    a_end > 0
)
SELECT echo,
       type,
       CASE c_end
       WHEN 0
       THEN SUBSTR( color, c_start )
       ELSE SUBSTR( color, c_start, c_end - c_start )
       END AS color,
       CASE a_end
       WHEN 0
       THEN SUBSTR( active, a_start )
       ELSE SUBSTR( active, a_start, a_end - a_start )
       END AS active
FROM   lines
ORDER BY rn, idx

Вывод :

ECHO  | TYPE | COLOR  | ACTIVE
:---- | :--- | :----- | :-----
echo1 | car  | yellow | yes   
echo1 | car  | green  | yes   
echo1 | car  | yellow | no    
echo1 | car  | green  | no    
echo1 | car  | blue   | no    
echo2 | car  | blue   | yes   
echo2 | car  | red    | yes   
echo2 | car  | green  | no    
echo2 | car  | blue   | no    
echo2 | car  | red    | no    
echo3 | car  | yellow | no    
echo3 | car  | green  | yes   

db <> fiddle здесь


Update

Не объединять, а затем разбивать строки с разделителями; просто извлеките значения из XML:

CREATE TABLE table_name ( xml_field ) AS
SELECT XMLTYPE( '<rowCollection>
  <row>
    <column name="active">YES</column>
    <column name="customertype">Default</column>
    <column name="type">Default</column>
    <column name="risklevel">Default</column>
    <column name="color">yellow</column>
  </row>
  <row>
    <column name="active">YES</column>
    <column name="customertype">Default</column>
    <column name="type">Default</column>
    <column name="risklevel">Default</column>
    <column name="color">green</column>
  </row>
</rowCollection>' ) FROM DUAL;

Запрос :

SELECT x.*
FROM   table_name t
       CROSS JOIN
       XMLTABLE(
         '/rowCollection/row'
         PASSING t.xml_field
         COLUMNS
           active VARCHAR2(3) PATH '/row/column[@name="active"]',
           type   VARCHAR2(10) PATH '/row/column[@name="type"]',
           color  VARCHAR2(10) PATH '/row/column[@name="color"]'
       ) x;

Выход :

Будет способ сгенерировать столбец echo; но это не входит в ваши данные.

ACTIVE | TYPE    | COLOR 
:----- | :------ | :-----
YES    | Default | yellow
YES    | Default | green 

db <> fiddle здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...