【问题标题】:Need oracle query to consolidate multiple rows into one with a column for each需要 oracle 查询将多行合并为一行,每行一列
【发布时间】:2019-08-20 17:39:49
【问题描述】:

我有以下数据集:

SELECT * FROM assets;    

AA_ASSET_ID ASSET_ID ASSET_NAME CLASS_ID CLASS_NAME
1023        1023     Head tip   4        Accessory
1023        1056     Sorter     2        Equipment
1023        1557     Workcell   1        Lab System

我想要一个可以将其输出到每个 aa_asset_id 一行的查询:

ID    Lab_System Equipment Accessory
1023  Workcell   Sorter    Head tip

我已经对 PIVOT 进行了修改,但无法完全使其正常工作。有没有办法让它输出?

【问题讨论】:

  • 它是 Oracle 12c
  • 只有 3 个 CLASS_NAME 吗?
  • 这可以通过 PIVOT 完成,但是您需要考虑几个问题(然后在此处回答,以便我们提供帮助)。 (1) 是否关心表中的其他数据,例如 ASSET_ID 和 CLASS_ID? (2) 是否所有类名事先已知(无需查看表中的数据)? (3) 列名是否以这种精确大小写(首字母大写,单词其余部分小写)是您要求的一部分?
  • 可能不止 3 个,但对于我的特定用例,我只对这 3 个感兴趣。
  • 类名是常量且已知的。它们位于相关表中,但不会更改。我知道 1,2,4 是我感兴趣的。是的,类名就是这种情况。

标签: sql oracle pivot


【解决方案1】:

使用条件聚合:

select
  aa_asset_id ID,
  max(case class_name when 'Lab System' then asset_name end) Lab_System,
  max(case class_name when 'Equipment' then asset_name end) Equipment,
  max(case class_name when 'Accessory' then asset_name end) Accessory
from assets
group by aa_asset_id

请参阅demo。
结果:

ID      LAB_SYSTEM  EQUIPMENT   ACCESSORY
1023    Workcell    Sorter      Head tip

【讨论】:

  • 这个似乎正在做我需要的。非常感谢大家。
【解决方案2】:

使用 PIVOT 运算符,您可以这样做:(注意 - WITH 子句不是解决方案的一部分;我只使用它是因为我没有您的实际表。在实际测试时将其删除表)

with
  assets (aa_asset_id, asset_id, asset_name, class_id, class_name) as (
    select 1023, 1023, 'Head tip', 4, 'Accessory'  from dual union all
    select 1023, 1056, 'Sorter'  , 2, 'Equipment'  from dual union all
    select 1023, 1557, 'Workcell', 1, 'Lab System' from dual
  )
select *
from   (select aa_asset_id, asset_name, class_name from assets)
pivot  (max(asset_name) for class_name in ('Lab System' as "Lab System",
                                           'Equipment'  as "Equipment" ,
                                           'Accessory'  as "Accessory" ))
;

AA_ASSET_ID Lab System Equipment Accessory
----------- ---------- --------  ---------
       1023 Workcell   Sorter    Head tip

【讨论】:

    【解决方案3】:

    您可以使用PIVOT

    SELECT *
    FROM (
          SELECT aa_asset_id, asset_name, class_name
          FROM   assets
          )
    PIVOT (
           MAX(asset_name) FOR (class_name) IN (
                                                'Lab System' as "Lab System", 
                                                'Equipment' as Equipment, 
                                                'Accessory' as Accessory )
          )
    

    或PIVOT XML,以便拥有动态列名而不是硬编码。

    可能是这样的

    SELECT *
    FROM (
          SELECT aa_asset_id, asset_name, class_name
          FROM   assets
         )
    PIVOT XML (
               MAX(asset_name) FOR (class_name) IN (SELECT DISTINCT class_name FROM assets)
              )
    

    【讨论】:

      【解决方案4】:

      您有机会使用MODEL 子句:

      select
        id, Lab_System, Equipment, Accessory
      from assets
      model
        return updated rows
        partition by (AA_ASSET_ID id)
        dimension by (CLASS_NAME)
        measures (
          asset_name,
          cast('' as varchar2(8)) Accessory,
          cast('' as varchar2(8)) Equipment,
          cast('' as varchar2(8)) LAB_SYSTEM
        ) rules (
          Accessory['PIVOT'] = asset_name['Accessory'],
          Equipment['PIVOT'] = asset_name['Equipment'],
          LAB_SYSTEM['PIVOT'] = asset_name['Lab System']
        );
      

      输出:

      |  ID  | LAB_SYSTEM | EQUIPMENT | ACCESSORY |
      +------+------------+-----------+-----------+
      | 1024 | Foo        | (null)    | Bar       |
      | 1023 | Workcell   | Sorter    | Head tip  |
      

      SQL Fiddle 上的演示。

      【讨论】:

        猜你喜欢
        • 2021-05-01
        • 1970-01-01
        • 2023-02-10
        • 1970-01-01
        • 1970-01-01
        • 2011-12-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多