【问题标题】:Oracle SQL - Transpose Column to Row GroupingOracle SQL - 将列转置为行分组
【发布时间】:2019-05-06 17:00:33
【问题描述】:

我在一个运行良好的 Oracle 11g 实例上运行以下 SQL 查询:

SELECT
    TRIM(PART_NM) || TRIM(PART_NO),
    TRIM(MKBY_IND),
    MFG_TYP

FROM
    TblPARTS

WHERE
    ORDER_START_DATE >= (SYSDATE - 365)
    AND
    TO_CHAR(TRIM(PART_NO)) != '99'

产生如下结果:

| Part | Make / Buy |    Area   |
|:----:|:----------:|:---------:|
| AU54 |      M     |    Demo   |
| ZA45 |      M     | Construct |
| AD28 |      B     | Construct |
| SX73 |      B     | Construct |
| MO47 |      M     | Construct |
| IN66 |      B     | Construct |
| RP42 |      M     |    Demo   |
| HF77 |      B     |    Demo   |
| IE43 |      B     |  Personal |
| OX11 |      B     |  Personal |
| ZE45 |      M     |    Demo   |
| JH21 |      M     | Construct |
| AM91 |      M     | Construct |
| DS50 |      M     |    Demo   |
| LE29 |      M     |    Demo   |
| IP91 |      M     |    Demo   |
| ID42 |      M     |    Demo   |
| RI96 |      M     |    Demo   |

我没有问题。但是,已要求我转置 Area 列,而是按它对行进行分组。类似于:

|    Part   | Make / Buy |
|:---------:|:----------:|
| CONSTRUCT |  CONSTRUCT |
|    AU54   |      M     |
|    ZA45   |      M     |
|    AD28   |      B     |
|    SX73   |      M     |
|    MO47   |      M     |
|    IN66   |      B     |
|    JH21   |      M     |
|    AM91   |      B     |
|    DEMO   |    DEMO    |
|    RP42   |      M     |
|    HF77   |      M     |
|    ZE45   |      M     |
|    DS50   |      B     |
|    LE29   |      M     |
|    IP91   |      M     |
|    ID42   |      M     |
|    RI96   |      M     |
|  PERSONAL |  PERSONAL  |
|    IE43   |      M     |
|    OX11   |      M     |

简而言之,我希望在“区域”列 (MFG_TYP) 字段中找到唯一值,并能够按它们连续分组。应该注意的是,列出的三个条目在我的数据集中是有效的,但可能会发生变化,因此我不是在寻找静态解决方案,而是在 Area 列中的所有唯一值上动态应用转换的方法.

我已尝试查看这些资源,但目前不了解如何构建解决方案。任何建议表示赞赏。

【问题讨论】:

  • 请提供对您有帮助的示例数据
  • 示例数据包含在帖子中。需要编辑什么? @Avi
  • 我只看到了您从查询中获得的结果和您的预期结果。
  • 是的。这不符合样本数据的条件吗? @阿维。我可以从桌子上做一个SELECT *,但我不知道这会有多大的好处。我很乐意为您提供任何您需要的帮助,但过去我也被告知要使用我目前拥有的东西,然后使用我的预期结果。

标签: sql oracle oracle11g grouping transpose


【解决方案1】:

ROLLUP Extension to GROUP BY 的快速解决方案:

with
  TblPARTS(Part, Make_Buy, Area) as (
    select 'AU54', 'M', 'Demo' from dual union all
    select 'ZA45', 'M', 'Construct' from dual union all
    select 'AD28', 'B', 'Construct' from dual union all
    select 'SX73', 'B', 'Construct' from dual union all
    select 'MO47', 'M', 'Construct' from dual union all
    select 'IN66', 'B', 'Construct' from dual union all
    select 'RP42', 'M', 'Demo' from dual union all
    select 'HF77', 'B', 'Demo' from dual union all
    select 'IE43', 'B', 'Personal' from dual union all
    select 'OX11', 'B', 'Personal' from dual union all
    select 'ZE45', 'M', 'Demo' from dual union all
    select 'JH21', 'M', 'Construct' from dual union all
    select 'AM91', 'M', 'Construct' from dual union all
    select 'DS50', 'M', 'Demo' from dual union all
    select 'LE29', 'M', 'Demo' from dual union all
    select 'IP91', 'M', 'Demo' from dual union all
    select 'ID42', 'M', 'Demo' from dual union all
    select 'RI96', 'M', 'Demo' from dual union all
    select 'AO42', 'M', 'Public' from dual union all
    select 'OA42', 'B', 'Public' from dual
  ),
  a as (
    select
      Part, Make_Buy, Area,
      GROUPING_ID(Area, Part, Make_Buy) gid
    from TblPARTS
    group by rollup(Area, (Part, Make_Buy))
    having GROUPING_ID(Area, Part, Make_Buy) < 7
  )
select
  coalesce(Part, Area) Part,
  coalesce(Make_Buy, Area) Make_Buy
from a
order by Area, gid desc

输出:

+------------+-----------+
|    PART    |  MAKE_BUY |
+------------+-----------+
| Construct  | Construct |
| AM91       | M         |
| IN66       | B         |
| JH21       | M         |
| SX73       | B         |
| ZA45       | M         |
| AD28       | B         |
| MO47       | M         |
| Demo       | Demo      |
| ZE45       | M         |
| RP42       | M         |
| RI96       | M         |
| LE29       | M         |
| IP91       | M         |
| ID42       | M         |
| HF77       | B         |
| AU54       | M         |
| DS50       | M         |
| Personal   | Personal  |
| OX11       | B         |
| IE43       | B         |
| Public     | Public    |
| OA42       | B         |
| AO42       | M         |
+------------+-----------+

使用Rextester在线测试。

【讨论】:

【解决方案2】:

看起来这就是您要查找的内容:

SELECT
    'CONSTRUCT' AS "Part",
    'CONSTRUCT' AS "Make / Buy"
FROM DUAL

UNION

SELECT
    TRIM(PART_NM) || TRIM(PART_NO) AS "Part",
    TRIM(MKBY_IND) AS "Make / Buy"
FROM
    TblPARTS
WHERE
    ORDER_START_DATE >= (SYSDATE - 365)
    AND    TO_CHAR(TRIM(PART_NO)) != '99'
    AND    MFG_TYP = 'Construct'

UNION

SELECT
    'DEMO' AS "Part",
    'DEMO' AS "Make / Buy"
FROM DUAL

UNION

SELECT
    TRIM(PART_NM) || TRIM(PART_NO) AS "Part",
    TRIM(MKBY_IND) AS "Make / Buy"
FROM
    TblPARTS
WHERE
    ORDER_START_DATE >= (SYSDATE - 365)
    AND    TO_CHAR(TRIM(PART_NO)) != '99'
    AND    MFG_TYP = 'Demo'

UNION

SELECT
    'PERSONAL ' AS "Part",
    'PERSONAL ' AS "Make / Buy"
FROM DUAL

UNION

SELECT
    TRIM(PART_NM) || TRIM(PART_NO)) AS "Part",
    TRIM(MKBY_IND) AS "Make / Buy"
FROM
    TblPARTS
WHERE
    ORDER_START_DATE >= (SYSDATE - 365)
    AND    TO_CHAR(TRIM(PART_NO)) != '99'
    AND    MFG_TYP = 'Personal'

【讨论】:

  • 如果有不止这三个MFG_TYP 字段,这怎么可能?意思是,这个数字是动态的。我怎么可能将这些调整为不是仅针对这三个静态,而是针对列中的所有唯一值执行此操作?
猜你喜欢
  • 1970-01-01
  • 2020-12-06
  • 2021-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-27
  • 2016-12-03
相关资源
最近更新 更多