【问题标题】:convert row data into column in oracle [duplicate]在oracle中将行数据转换为列[重复]
【发布时间】:2018-11-11 07:16:55
【问题描述】:

我有一个表mapping,其中包含code 列和如下所示的值。

A
B
C
D

我想将此行级数据转换为列,如

column1 column2 column3 column4

A B C D

哪位大神可以帮忙看看

另外,我不想在查询中对我的表数据进行硬编码,因为数据可能每天都不同。

【问题讨论】:

  • 我不想在查询中硬编码我的表数据。
  • 我认为您可以创建一个存储过程,在其中创建一个临时表并将选择返回到该临时表。如果您需要帮助来详细说明,请告诉我:)
  • 这里的重点是您可以拥有可变数量的记录,因此您的结果将具有可变数量的列。你会怎么处理?例如,在事先不知道结果列的情况下,您无法获取值、循环游标……请添加一些有关如何使用此类查询结果的信息
  • 如果 OP 在动态列数上,则此问题与 stackoverflow.com/q/15491661/1509264 重复

标签: sql oracle


【解决方案1】:

如果您希望查询能够提供可变数量的列,则一种方法可能是动态 SQL;例如,无论记录数如何,此查询都将构建一个完成这项工作的查询:

select 
        'select *
        from
            mapping
        pivot ( max(code) for code in (' ||
        listagg('''' || code || ''' AS column' || n, ',') within group (order by code) ||
        '))'
from (select code, rownum n from mapping)

这给出了这个查询:

select *
from
    mapping
pivot ( max(code) for code in ('A' AS column1,'B' AS column2,'C' AS column3,'D' AS column4))

给出:

COLUMN1 COLUMN2 COLUMN3 COLUMN4
------- ------- ------- -------
A       B       C       D      
1 row selected.

现在的问题是你将如何使用它;您可以使用execute immediate 运行动态查询,但这里您事先不知道列数,因此您无法将该查询的结果获取到任何内容中。

另一种方法是生成 XML 结果,例如:

select 
        dbms_xmlgen.getxml(
            'select *
            from
                mapping
            pivot ( max(code) for code in (' ||
            listagg('''' || code || ''' AS column' || n, ',') within group (order by code) ||
            '))'
        )

给予:

<?xml version="1.0"?>
<ROWSET>
 <ROW>
  <COLUMN1>A</COLUMN1>
  <COLUMN2>B</COLUMN2>
  <COLUMN3>C</COLUMN3>
  <COLUMN4>D</COLUMN4>
 </ROW>
</ROWSET>
from (select code, rownum n from mapping)

【讨论】:

    【解决方案2】:

    使用PIVOT:

    SQL Fiddle

    Oracle 11g R2 架构设置

    CREATE TABLE mapping ( code ) AS
    SELECT 'A' FROM DUAL UNION ALL
    SELECT 'B' FROM DUAL UNION ALL
    SELECT 'C' FROM DUAL UNION ALL
    SELECT 'D' FROM DUAL;
    

    查询 1

    SELECT *
    FROM   (
      SELECT ROW_NUMBER() OVER ( ORDER BY code ) rn,
             code
      FROM   mapping
    )
    PIVOT ( MAX( code ) FOR rn IN (
      1 AS column1,
      2 AS column2,
      3 AS column3,
      4 AS coumn4
    ) )
    

    Results

    | COLUMN1 | COLUMN2 | COLUMN3 | COUMN4 |
    |---------|---------|---------|--------|
    |       A |       B |       C |      D |
    

    【讨论】:

    • 由于我的表中目前只有四个值,因此我们给出了1 2 3 4。但是明天我只能有 3 个然后我需要再次更改我的代码。这在生产环境中是不可能的。
    • @teepu 查询具有固定数量的列 - 如果您没有固定数量的列,那么您需要将值输出为行并将其转置到中间件中的列层(最佳解决方案)或使用动态 SQL 创建具有适当列数的查询(这很慢、复杂且难以维护)。
    • 如何使用动态查询来实现?
    【解决方案3】:

    检查下面的查询。

    select listagg(CODE,' ') within group(order by CODE) CODE
    from tableName
    

    检查此Demo

    【讨论】:

    • 谢谢,我希望每一行都在每一列下。我已经更新了我的数据。
    • @teepu 答案基于您发布的问题和数据。
    • 我已经更新了我的预期数据
    猜你喜欢
    • 2014-01-27
    • 1970-01-01
    • 2019-10-14
    • 2020-02-23
    • 2019-09-13
    • 2017-06-28
    • 1970-01-01
    • 2021-03-02
    • 2021-08-07
    相关资源
    最近更新 更多