/ / Oracle przecinek rozdzielony na wiersze z grupowaniem - wyrocznia

Przecinek Oracle rozdzielony na wiersze z grupowaniem - wyrocznia

Mam następujący wymóg. Czy w wyroczni 12c są dostępne bezpośrednie funkcje, aby to osiągnąć?

create table t1(input_name varchar2(500),input_values varchar2(500));
insert into t1 values("a,b,c,d,","1,2,3,4");
insert into t1 values("e,f,g,","5,6,7");
insert into t1 values("a1,b1,c1,d1,","11,12,13,14");
insert into t1 values("d,c,b,a,","100,200,300,400");
commit;

select * from t1;
INPUT_NAME                     INPUT_VALUES
------------------------------ ----------------
a,b,c,d,                       1,2,3,4
e,f,g,                         5,6,7
a1,b1,c1,d1,                   11,12,13,14
d,c,b,a,                       100,200,300,400

output:
a   b   c   d   e f g a1 b1 c1 d1
1   2   3   4   5 6 7 11 12 13 14
400 300 200 100

Dzięki, Rahmat Ali

Odpowiedzi:

1 dla odpowiedzi № 1

Tak ... jeśli masz znany zestaw nazw wejść. Ale lepiej byłoby przeorganizować swoje dane, aby nie przechowywać skorelowanych par list oddzielonych przecinkami.

SQL Fiddle

Oracle 11g R2 Schema Setup:

create table t1(input_name,input_values) AS
SELECT "a,b,c,d,","1,2,3,4" FROM DUAL UNION ALL
SELECT "e,f,g,","5,6,7" FROM DUAL UNION ALL
SELECT "a1,b1,c1,d1,","11,12,13,14" FROM DUAL UNION ALL
SELECT "d,c,b,a,","100,200,300,400" FROM DUAL
/
CREATE TYPE pair IS OBJECT(
name  VARCHAR2(20),
value VARCHAR2(20)
)
/

CREATE TYPE pair_table IS TABLE OF PAIR
/

Zapytanie 1:

SELECT MAX( CASE name WHEN "a" THEN value END ) AS a,
MAX( CASE name WHEN "b" THEN value END ) AS b,
MAX( CASE name WHEN "c" THEN value END ) AS c,
MAX( CASE name WHEN "d" THEN value END ) AS d,
MAX( CASE name WHEN "e" THEN value END ) AS e,
MAX( CASE name WHEN "f" THEN value END ) AS f,
MAX( CASE name WHEN "g" THEN value END ) AS g,
MAX( CASE name WHEN "a1" THEN value END ) AS a1,
MAX( CASE name WHEN "b1" THEN value END ) AS b1,
MAX( CASE name WHEN "c1" THEN value END ) AS c1,
MAX( CASE name WHEN "d1" THEN value END ) AS d1
FROM   (
SELECT v.name,
v.value,
ROW_NUMBER() OVER ( PARTITION BY v.name ORDER BY ROWNUM ) AS rn
FROM   t1 t
CROSS JOIN
TABLE(
CAST(
MULTISET(
SELECT pair(
REGEXP_SUBSTR( t.input_name,   "([^,]+)(,|$)", 1, LEVEL, NULL, 1 ),
REGEXP_SUBSTR( t.input_values, "([^,]+)(,|$)", 1, LEVEL, NULL, 1 )
)
FROM   DUAL
CONNECT BY level <= REGEXP_COUNT( t.input_name, "([^,]+)(,|$)" )
) AS pair_table
)
) v
)
GROUP BY rn

Wyniki:

|   A |   B |   C |   D |      E |      F |      G |     A1 |     B1 |     C1 |     D1 |
|-----|-----|-----|-----|--------|--------|--------|--------|--------|--------|--------|
|   1 |   2 |   3 |   4 |      5 |      6 |      7 |     11 |     12 |     13 |     14 |
| 400 | 300 | 200 | 100 | (null) | (null) | (null) | (null) | (null) | (null) | (null) |

Możesz także użyć a PIVOT oświadczenie, a nie wielokrotność MAX( CASE ... END ) sprawozdania.

Jeśli nie masz statycznego zestawu nazw wejściowych, będziesz musiał wyszukać dynamiczne pivoty.

Aktualizacja:

Czy jest sposób, w jaki mogę uniknąć używania czcionek?

Możesz uniknąć tworzenia typów i po prostu użyć wbudowanego VARRAY lub kolekcja jak SYS.ODCIVARCHAR2LIST ale wtedy będziesz potrzebować dwóch list i korelacja między nimi staje się skomplikowana.

WITH input_names ( rid, idx, name ) AS (
SELECT t.ROWID,
ROW_NUMBER() OVER ( PARTITION BY t.ROWID ORDER BY ROWNUM ) AS rn,
v.COLUMN_VALUE
FROM   t1 t
CROSS JOIN
TABLE(
CAST(
MULTISET(
SELECT REGEXP_SUBSTR( t.input_name,   "([^,]+)(,|$)", 1, LEVEL, NULL, 1 )
FROM   DUAL
CONNECT BY level <= REGEXP_COUNT( t.input_name, "([^,]+)(,|$)" )
) AS SYS.ODCIVARCHAR2LIST
)
) v
),
input_values ( rid, idx, value ) AS (
SELECT t.ROWID,
ROW_NUMBER() OVER ( PARTITION BY t.ROWID ORDER BY ROWNUM ) AS rn,
v.COLUMN_VALUE
FROM   t1 t
CROSS JOIN
TABLE(
CAST(
MULTISET(
SELECT REGEXP_SUBSTR( t.input_values,   "([^,]+)(,|$)", 1, LEVEL, NULL, 1 )
FROM   DUAL
CONNECT BY level <= REGEXP_COUNT( t.input_values, "([^,]+)(,|$)" )
) AS SYS.ODCIVARCHAR2LIST
)
) v
),
correlated ( name, value, rn ) AS (
SELECT n.name,
v.value,
ROW_NUMBER() OVER ( PARTITION BY n.name
ORDER BY ROWNUM )
FROM   input_names n
INNER JOIN
input_values v
ON ( n.rid = v.rid AND n.idx = v.idx )
)
SELECT MAX( CASE name WHEN "a" THEN value END ) AS a,
MAX( CASE name WHEN "b" THEN value END ) AS b,
MAX( CASE name WHEN "c" THEN value END ) AS c,
MAX( CASE name WHEN "d" THEN value END ) AS d,
MAX( CASE name WHEN "e" THEN value END ) AS e,
MAX( CASE name WHEN "f" THEN value END ) AS f,
MAX( CASE name WHEN "g" THEN value END ) AS g,
MAX( CASE name WHEN "a1" THEN value END ) AS a1,
MAX( CASE name WHEN "b1" THEN value END ) AS b1,
MAX( CASE name WHEN "c1" THEN value END ) AS c1,
MAX( CASE name WHEN "d1" THEN value END ) AS d1
FROM   correlated
GROUP BY rn;