2015-12-24 2 views
2

У меня есть данные в таблице, которая выглядит как:Разбиение строки на столбцы в оракула

enter image description here

Я хочу, чтобы разделить свои данные и сделать его выглядеть следующим образом через SQL-запрос в Oracle (без использования ось):

enter image description here

Как это можно сделать ?? есть ли другой способ сделать это без использования шарнира?

+0

Вы должны использовать либо стержень ANSI-стиль или встроенную Oracle в функции 'PIVOT' (если вы используете 11g или более поздней версии). Я не могу думать иначе. –

ответ

3

Вам необходимо использовать сводный запрос h прежде чем получить вывод, который вы хотите:

SELECT Name, 
     MIN(CASE WHEN ID_Type = 'PAN'  THEN ID_No ELSE NULL END) AS PAN, 
     MIN(CASE WHEN ID_Type = 'DL'  THEN ID_No ELSE NULL END) AS DL, 
     MIN(CASE WHEN ID_Type = 'Passport' THEN ID_No ELSE NULL END) AS Passport 
FROM yourTable 
GROUP BY Name 

Вы также можете попробовать использовать Oracle, встроенный в PIVOT() функции, если вы работаете в версии 11g или более поздней версии.

+0

Под капотом Oracle использует «MAX» и «CASE» для PIVOT. Производительность одинакова, это всего лишь код с PIVOT. Вы можете проверить это с помощью процедуры 'EXPAND_SQL_TEXT', приведенной в 12c. –

+1

Хорошо, закончил! ... это зимний баш. Мы хотим шляпы ;-) –

2

Поскольку вы упоминаете без использования функции PIVOT, вы можете попробовать: использовать SQL внутри группы для перемещения строк в одну строку и listagg для отображения нескольких значений столбцов в одном столбце.

В Oracle 11g, можно использовать встроенную функцию listagg:

select 
    deptno, 
    listagg (ename, ',') 
    WITHIN GROUP 
    (ORDER BY ename) enames 
FROM 
emp 
GROUP BY 
deptno 

который должен дать вам результат ниже:

DEPTNO ENAMES            
------ -------------------------------------------------- 
    10 CLARK,KING,MILLER         
    20 ADAMS,FORD,JONES,SCOTT,SMITH     
    30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD  

Вы можете найти все решения (s) к этой проблеме: http://www.dba-oracle.com/t_converting_rows_columns.htm

+0

Кроме того, имейте в виду, что возвращаемый тип listagg - VARCHAR2. Учитывайте ограничение размера списка. – Skoffer

+0

Как это ответить на вопрос OP вообще? 'LISTAGG' - это агрегация строк, а OP - разные столбцы. если вы не можете использовать 'PIVOT', то альтернативой является' MAX' и 'CASE'. Под капотом Oracle делает то же самое с PIVOT. Вы можете проверить это с помощью процедуры 'EXPAND_SQL_TEXT', приведенной в 12c. –

+0

@LalitKumarB: Мой ответ был больше основан на представлении данных в горизонтальном формате от вертикального. Это, конечно же, с гонщиком, что вам нужно подделать столбец 'ENAMES' для получения отдельных значений по мере необходимости. –

0

Вы можете использовать CTE, чтобы разбить данные вниз, а затем соединить их вместе, чтобы получить то, что вы хотите:

WITH NAMES AS (SELECT DISTINCT NAME 
       FROM YOURTABLE), 
    PAN AS (SELECT NAME, ID_NO AS PAN 
       FROM YOURTABLE 
       WHERE ID_TYPE = 'PAN'), 
    DL AS (SELECT NAME, ID_NO AS DL 
       FROM YOURTABLE 
       WHERE ID_TYPE = 'DL'), 
    PASSPORT AS (SELECT NAME, ID_NO AS "Passport" 
        FROM YOURTABLE 
        WHERE ID_TYPE = 'Passport') 
SELECT n.NAME, p.PAN, d.DL, t."Passport" 
    FROM NAMES n 
    LEFT OUTER JOIN PAN p 
    ON p.NAME = n.NAME 
    LEFT OUTER JOIN DL d 
    ON d.NAME = p.NAME 
    LEFT OUTER JOIN PASSPORT t 
    ON t.NAME = p.NAME' 

Заменить YOURTABLE с действительным именем вашей таблицы интереса.

Удачи.

1

Для Oracle 11g и выше вы можете использовать PIVOT.

для выпуска до 11g, вы можете использовать MAX и СЛУЧАЙ.

A common misconception, о PIVOT лучше с точки зрения производительности, чем старый способ MAX и DECODE. Но под капотом PIVOT такой же MAX + CASE. Вы можете проверить его в 12c, где Oracle добавлена ​​EXPAND_SQL_TEXT процедура DBMS_UTILITY упаковка.

Например,

SQL> variable c clob 
SQL> begin 
    2  dbms_utility.expand_sql_text(Q'[with choice_tbl as (
    3      select 'Jones' person,1 choice_nbr,'Yellow' color from dual union all 
    4      select 'Jones',2,'Green' from dual union all 
    5      select 'Jones',3,'Blue' from dual union all 
    6      select 'Smith',1,'Orange' from dual 
    7     ) 
    8 select * 
    9 from choice_tbl 
10 pivot(
11   max(color) 
12   for choice_nbr in (1 choice_nbr1,2 choice_nbr2,3 choice_nbr3) 
13  )]',:c); 
14 end; 
15/

PL/SQL procedure successfully completed. 

Теперь давайте посмотрим, что на самом деле делает Oracle внутренне:

SQL> set long 100000 
SQL> print c 

C 
-------------------------------------------------------------------------------- 
SELECT "A1"."PERSON" "PERSON", 
     "A1"."CHOICE_NBR1" "CHOICE_NBR1", 
     "A1"."CHOICE_NBR2" "CHOICE_NBR2", 
     "A1"."CHOICE_NBR3" "CHOICE_NBR3" 
    FROM (
     SELECT "A2"."PERSON" "PERSON", 
       MAX(CASE WHEN ("A2"."CHOICE_NBR"=1) THEN "A2"."COLOR" END) "CHOICE_NBR1", 
       MAX(CASE WHEN ("A2"."CHOICE_NBR"=2) THEN "A2"."COLOR" END) "CHOICE_NBR2", 
       MAX(CASE WHEN ("A2"."CHOICE_NBR"=3) THEN "A2"."COLOR" END) "CHOICE_NBR3" 
      FROM (
       (SELECT 'Jones' "PERSON",1 "CHOICE_NBR",'Yellow' "COLOR" FROM "SYS"."DUAL" "A7") UNION ALL 
       (SELECT 'Jones' "'JONES'",2 "2",'Green' "'GREEN'" FROM "SYS"."DUAL" "A6") UNION ALL 
       (SELECT 'Jones' "'JONES'",3 "3",'Blue' "'BLUE'" FROM "SYS"."DUAL" "A5") UNION ALL 
       (SELECT 'Smith' "'SMITH'",1 "1",'Orange' "'ORANGE'" FROM "SYS"."DUAL" "A4") 
       ) "A2" 
      GROUP BY "A2"."PERSON" 
     ) "A1" 
SQL> 

Oracle внутренне интерпретирует PIVOT в MAX + ДЕЛУ.

1

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

select * 
from yourTable 
pivot 
(
    max (id_no) 
    for (id_type) in ('PAN' as pan, 'DL' as dl, 'Passport' as passport) 
) 

Что стержень делает GROUP BY все столбцы не указано в предложении PIVOT (на самом деле, просто name), выбирая новые столбцы в режиме подзапроса на основе агрегатов до предложения FOR для каждого значения, указанного в предложении IN, и отбрасывая эти столбцы, указанные в разделе PIVOT.

Когда я говорю «способ подзапроса», я имею в виду один из способов достижения результата, полученного с помощью PIVOT. На самом деле, я не знаю, как это работает за кулисами. Этот подзапрос мода будет выглядеть так:

select <aggregation> 
from <yourTable> 
where 1=1 
    and <FORclauseColumns> = <INclauseValue> 
    and <subqueryTableColumns> = <PIVOTgroupedColumns> 

Теперь вы определили, каким образом вы можете создать запрос без PIVOT пункта:

select 
    name, 
    (select max(id_no) from yourTable where name = t.name and id_type = 'PAN') as pan, 
    (select max(id_no) from yourTable where name = t.name and id_type = 'DL') as dl, 
    (select max(id_no) from yourTable where name = t.name and id_type = 'Passport') as passport 
from yourTable t 
group by name 
Смежные вопросы