答案 0 :(得分:3)
您需要在此处使用数据透视查询来获取所需的输出:
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
如果您运行的是11g或更高版本,也可以尝试使用Oracle内置的PIVOT()
函数。
答案 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
您可以在此处找到此问题的所有解决方案: http://www.dba-oracle.com/t_converting_rows_columns.htm
答案 2 :(得分:1)
对于Oracle 11g及更高版本,您可以使用 PIVOT 。
对于11g之前的版本,您可以使用 MAX 和 CASE 。
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 + CASE 。
答案 3 :(得分:1)
您可以通过了解透视查询的功能来创建非透视查询:
select *
from yourTable
pivot
(
max (id_no)
for (id_type) in ('PAN' as pan, 'DL' as dl, 'Passport' as passport)
)
透视图所做的是GROUP BY
未在PIVOT
子句中指定的所有列(实际上只是名称列),以子查询方式选择新列基于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
答案 4 :(得分: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
替换为您感兴趣的表格的实际名称。
祝你好运。