【问题标题】:Oracle 12c Pivoting data rows to columnsOracle 12c 将数据行转换为列
【发布时间】:2017-03-13 17:41:23
【问题描述】:

我有一个 Oracle 12c 透视问题。

我需要创建一行数据来显示客户在给定时间对其个人资料所做的更改,以便我可以将我的日期移至仓库结构。数据被归一化为表格 Investor (INV)、Phone(PHH)、Email(EMH)。

我创建了一个查询,它为我提供了非常基础的信息,包括哪位投资者、发生了什么变化、何时发生的变化,以及一个指向我需要的信息的指针,其中每行发生的表变化。我想将这些数据转换为单行,然后使用这些行获取其他数据。

当我尝试运行我的数据透视查询时,我得到 ORA-56901 非常量表达式是不允许的。我以为我使用的是 TABLE_ALIAS 列中的常量。这是我第一次尝试使用这种语法。我使用了此处和其他网站上发布的其他有关旋转的问题的示例来帮助我构建查询。有人可以帮我理解我哪里出错了吗?谢谢!

我的查询结果表示如下:

  CREATE   TABLE "DBO"."CHANGES"
  (
    "MY_ROW_ID"        NUMBER NOT NULL ENABLE,
    "WHEN_IT_HAPPENED" TIMESTAMP (6) NOT NULL ENABLE,
    "INVESTOR_ID"      NUMBER NOT NULL ENABLE,
    "HISTORY_ID"       NUMBER NOT NULL ENABLE,
    "TABLE_ALIAS"      VARCHAR2(7 BYTE) NOT NULL ENABLE,
    CONSTRAINT "CHANGES_PK" PRIMARY KEY ("MY_ROW_ID") USING INDEX PCTFREE 10
    INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS TABLESPACE "USERS" ENABLE
  )  ;

添加数据:

Insert into DBO.CHANGES values (1,to_timestamp('08-MAR-2017 11.47.46.717417000 AM','DD-MON-YYYY HH.MI.SSXFF AM'),2158,2186,'IVH');
Insert into DBO.CHANGES values (2,to_timestamp('08-MAR-2017 11.47.46.717417000 AM','DD-MON-YYYY HH.MI.SSXFF AM'),2158,2508,'PHH2');
Insert into DBO.CHANGES values (3,to_timestamp('08-MAR-2017 11.46.25.284464000 AM','DD-MON-YYYY HH.MI.SSXFF AM'),2158,2507,'EMH');
Insert into DBO.CHANGES values (4,to_timestamp('08-MAR-2017 10.28.13.366506000 AM','DD-MON-YYYY HH.MI.SSXFF AM'),1004,2490,'EMH');
Insert into DBO.CHANGES values (5,to_timestamp('08-MAR-2017 10.33.46.101412000 AM','DD-MON-YYYY HH.MI.SSXFF AM'),1004,2153,'IVH');
Insert into DBO.CHANGES values (6,to_timestamp('08-MAR-2017 12.11.58.539055000 PM','DD-MON-YYYY HH.MI.SSXFF AM'),1004,2166,'IVH');
Insert into DBO.CHANGES values (7,to_timestamp('08-MAR-2017 12.11.58.539055000 PM','DD-MON-YYYY HH.MI.SSXFF AM'),1004,2046,'PHH1');

这是我为几个投资者提供的一些数据:

MY_ROW_ID   WHEN_IT_HAPPENED    INVESTOR_ID HISTORY_ID TABLE_ALIAS
1   08-MAR-2017 11.47.46.717417000  2158        2186        IVH
2   08-MAR-2017 11.47.46.717417000  2158        2508        PHH2
3   08-MAR-2017 11.46.25.284464000  2158        2507        EMH
4   08-MAR-2017 10.28.13.366506000  1004        2490        EMH 
5   08-MAR-2017 10.33.46.101412000  1004        2153        IVH
6   08-MAR-2017 12.11.58.539055000  1004        2166        IVH
7   08-MAR-2017 12.11.58.539055000  1004        2046        PHH1

我想看到的是这样的:

INVESTOR_ID  WHEN_IT_HAPPENED           IVH     PHH1    PHH2    EMH
1004    08-MAR-2017 10.28.13.366506000                          2490
1004    08-MAR-2017 10.33.46.101412000  2153
1004    08-MAR-2017 12.11.58.539055000  2166    2046
2158    08-MAR-2017 11.47.46.717417000  2186            2508
2158    08-MAR-2017 11.46.25.284464000                          2507

这是我尝试过的:

SELECT    INVESTOR_ID
        , WHEN_IT_HAPPENED
        , IVH
        , PHH1
        , PHH2
        , EMH
FROM      ( SELECT    INVESTOR_ID
                    , WHEN_IT_HAPPENED
                    , TABLE_ALIAS
                    , HISTORY_ID
            FROM      CHANGES
           )
PIVOT
(
  MAX (HISTORY_ID)
  FOR  TABLE_ALIAS
  IN  ( IVH, PHH1, PHH2, EMH )
 )   ;

ORA-56901: 枢轴|非枢轴值不允许非常量表达式 56901. 0000 - “枢轴|非枢轴值不允许非常量表达式” *原因:试图对枢轴|非枢轴值使用非常量表达式。 *行动:使用常量作为枢轴|非枢轴值。 行错误:17 列:9(这是我的枢轴 IN 子句)

更新

非常感谢您的帮助。我确定可能还有其他方法,但是以下方法对我有用。有了这个新工具,我现在可以创建查询来获取所需的所有数据。

SELECT    INVESTOR_ID
        , WHEN_IT_HAPPENED
        , IVH_HIST_ID
        , PHH1_HIST_ID
        , PHH2_HIST_ID
        , PHH3_HIST_ID
--SELECT      *  -- this works too.  I just prefer to list things for clarity.
FROM      ( SELECT    INVESTOR_ID
                    , WHEN_IT_HAPPENED
                    , TABLE_ALIAS
                    , HISTORY_ID
            FROM      CHANGES
           )
PIVOT
(
  MIN (HISTORY_ID)  AS HIST_ID
  FOR  TABLE_ALIAS 
  IN  (   'IVH'   AS  IVH
        , 'PHH1'  AS  PHH1
        , 'PHH2'  AS  PHH2
        , 'PHH3'  AS  PHH3
       )
 )  
 ORDER BY INVESTOR_ID
        , WHEN_IT_HAPPENED
 ;

【问题讨论】:

    标签: oracle pivot oracle12c


    【解决方案1】:
      FOR  TABLE_ALIAS
      IN  ( 'IVH', 'PHH1', 'PHH2', 'EMH' )
    

    列表中的项目是字符串,它们必须用单引号括起来。像'IVH' 这样的字符串是一个常量表达式(VARCHAR2 数据类型);没有引号,IVH 被解释为列名,而不是常量。 (一个甚至不存在的列名,但解析器并没有寻找它,因为它认为它甚至在此之前就发现了一个语法错误。)

    【讨论】:

    • 我觉得自己像个傻瓜!非常感谢,我需要另一双眼睛。
    • @datadesigner - 不用担心,我一直都这样做(而且通常另一双眼睛确实是正确的解决方案)。
    【解决方案2】:

    这对我有用。

    SELECT    * from 
    (select investor_id, when_it_happened, history_id, table_alias from changes)
    PIVOT
    (
      MAX (HISTORY_ID) as history_id
      FOR  TABLE_ALIAS
      IN  ( 'IVH', 'PHH1', 'PHH2', 'EMH' )
     )   ;
    

    【讨论】:

      猜你喜欢
      • 2019-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多