如何在Oracle中将行转换为列?

20

我有一个表格,形式如下(这只是部分视图,该表格包含100多列)。

 LOAN NUMBER   DOCUMENT_TYPE                DOCUMENT_ID
 992452533663  Voters ID                    XPD0355636
 992452533663  Pan card                     CHXPS5522D
 992452533663  Drivers licence              DL-0420110141769
对于一个贷款号,我有三种文件作为证明。我希望这些细节被转化为列,并采取以下形式:
LOAN NUMBER     VOTERS_ID    PAN_CARD     DRIVERS LICENCE
992452533663    XPD0355636   CHXPS5522D   DL-0420110141769

如何开始?


3
在提出问题之前,请考虑先搜索相关内容,这样可以节省时间并更快地得到答案。参考链接为:http://stackoverflow.com/questions/5301613/inverse-row-to-column/5301689#5301689 - SQLMason
请查看此问题的答案以获取动态选项。 - Barbaros Özhan
只是提醒一下,虽然问题可能是重复的,但是不同的答案在这种情况下有帮助。两个链接中的解决方案对我都不起作用。但是这里的解决方案却行得通。 - ragethewolf
3个回答

23
如果您使用的是 Oracle 10g,您可以使用 DECODE 函数将行转换为列:
CREATE TABLE doc_tab (
  loan_number VARCHAR2(20),
  document_type VARCHAR2(20),
  document_id VARCHAR2(20)
);

INSERT INTO doc_tab VALUES('992452533663', 'Voters ID', 'XPD0355636');
INSERT INTO doc_tab VALUES('992452533663', 'Pan card', 'CHXPS5522D');
INSERT INTO doc_tab VALUES('992452533663', 'Drivers licence', 'DL-0420110141769');

COMMIT;

SELECT
    loan_number,
    MAX(DECODE(document_type, 'Voters ID', document_id)) AS voters_id,
    MAX(DECODE(document_type, 'Pan card', document_id)) AS pan_card,
    MAX(DECODE(document_type, 'Drivers licence', document_id)) AS drivers_licence
  FROM
    doc_tab
GROUP BY loan_number
ORDER BY loan_number;

输出:

LOAN_NUMBER   VOTERS_ID            PAN_CARD             DRIVERS_LICENCE    
------------- -------------------- -------------------- --------------------
992452533663  XPD0355636           CHXPS5522D           DL-0420110141769     

你可以使用在Oracle 11g中引入的PIVOT子句来实现相同的效果:

SELECT *
  FROM doc_tab
PIVOT (
  MAX(document_id) FOR document_type IN ('Voters ID','Pan card','Drivers licence')
);

SQLFiddle示例,包含两种解决方案:SQLFiddle示例

了解更多关于数据透视的信息,请访问:Tim Hall的Oracle数据透视


难道dasblinkenlight发布的第一种方法不是更好、更优雅的解决方案吗?能否请您指点一二? - MontyPython
3
@MontyPython,我已经给出了同时适用于Oracle 10g和11g的解决方案。由于您没有写出您的Oracle版本,我提供了一种适用于两个版本的解决方案。PIVOT是由dasblinkenlight使用的,在Oracle 11g之前的版本中不可用。 - Przemyslaw Kruglej
我错过了。 我使用11g,我是Oracle的新手。 虽然感谢两种解决方案。确实非常有帮助。 - MontyPython
1
喜欢这个答案,因为它在限制访问的数据库中也可以工作。基本上,当我们无法使用数据透视表时,我们只能通过SAP BO访问Oracle。 - ragethewolf

15
你可以使用一个像这样的 pivot 查询 来实现它:
select * from (
   select LOAN_NUMBER, DOCUMENT_TYPE, DOCUMENT_ID
   from my_table t
)
pivot 
(
   MIN(DOCUMENT_ID)
   for DOCUMENT_TYPE in ('Voters ID','Pan card','Drivers licence')
)

这里是在sqlfiddle.com上的演示


你好。有没有办法动态地获取in子句中的值? - PKS
只要"in"情况的数量固定,是的;否则不行。 - Sergey Kalinichenko

8

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接