【问题标题】:Oracle SQL Pivot Command Not Working -- "Invalid Idenitifier"Oracle SQL Pivot 命令不起作用——“标识符无效”
【发布时间】:2021-12-07 13:50:54
【问题描述】:

我正在尝试使用 Pivot 在 Oracle SQL 中进行简单查询。我的表中有 12 列,但只有前四列是有意义的。列是“FACILITY_ID”(唯一标识符)、“REPORTING_YEAR”(报告的年份数据)、“SUBPART”(希望以 A 和 Z 之间可接受的值作为数据透视的数据类别)和“CO2E”(报告的浮点数)。我只想从子部分 C 和 K(第三列)中获取数据并将它们添加到自己的列中。

例如:
如果我的原始表格如下所示:

FACILITY_ID --- REPORTING_YEAR --- SUBPART --- CO2E  
10    -------------- 2020 ---------------------- C  -------- 10  
11    -------------- 2020 ---------------------- K  -------- 20  
10    -------------- 2020 ---------------------- K  -------- 40  
10    -------------- 2020 ---------------------- K  -------- 40  
11    -------------- 2020 ---------------------- C  -------- 30

我想得到类似的东西:

FACILITY_ID --- REPORTING_YEAR ----- C ----- K    
10    -------------- 2020 ----------------- 10  ----- 80  
11    -------------- 2020 ----------------- 30  ----- 20  

我现在的代码如下:

Create Table CandK_emissions as
  Select
    FACILITY_ID,
    REPORTING_YEAR,
    SUBPART,
    CO2E
  From
    facilityReport
  Pivot
  (
     Sum(CO2E)
     For SUBPART
     in ('C',
     'K')
  )

我得到的错误是“Ora-00904: "CO2e": Invalid Identifier'。我仔细检查了所有内容是否拼写正确。我不确定我哪里出错了。

【问题讨论】:

  • 已移除,谢谢@jarlh
  • 出了点问题。在其他地方,您要么显示 CO2E(不在双引号中,所以大写无关紧要)或全大写和双引号中的“CO2E”(使名称区分大小写)。但是错误消息抱怨“CO2e”带有小写“e”,这可能是问题所在 - 但您说“您检查了所有内容是否拼写正确”。我不认为 Oracle 自己将 E 更改为 e,即使在错误消息中显示它也是如此。可能是你检查的不够仔细?
  • 解决了这个问题后,您可能会发现您的查询实际上不起作用。 PIVOT 假定数据必须按 PIVOT 子句中未引用的所有列进行分组;因此,如果出于“分组”的目的必须忽略其他一些列,则不应从整个表中选择(然后透视),而应从仅从基表中选择相关列的内联子查询中进行选择。跨度>
  • @mathguy 你可以忽略大写。它在我的实际 Oracle 中全部大写。我只是重新键入并稍微更改了名称,因为由于 VDI 原因我无法复制和粘贴它。我将尝试首先选择四列并制作表格或更改我的查询。我对这一切都很陌生
  • 好的,抱歉 - 我现在看到了问题。在您当前的查询中(无论它最终是否会执行您需要的操作),您将 SUM(CO2E) 旋转为 (....)。旋转后,结果中没有 CO2E 列; CO2E 的总和将出现在 C 列或 K 列中。那么,CO2E 在 SELECT 子句中做了什么?这就是导致该错误的原因。与子部分相同。您应该选择 C ​​和 K。SELECT 子句应该显示将出现在输出中的列(而不是输入表中存在的列)。

标签: sql oracle pivot


【解决方案1】:

SELECT 子句必须显示输出中将存在哪些列,而不是使用基表中的哪些列。在您的查询中,您正在汇总 CO2E 值,分别针对不同的 SUBPART 值。旋转的结果不再有 CO2E 值或 SUBPART 值;相反,您感兴趣的两个 SUBPART 值 C 和 K 在输出中成为两个不同的列,并且 CO2E 的总和出现在这两个新列中。

您的查询应选择列 C 和 K;错误消息告诉您旋转后,没有可供选择的 CO2E 列。 (在你改变它之后,它会告诉你关于 SUBPART 的同样的事情。)

这应该是这样的。注意一些事情:在“测试数据”中,我模拟了另外一个列,一个名为 PK 的主键,以证明您必须首先在内联视图中排除它(FROM 子句中的子选择)。另请注意,为了使 PIVOT 尽可能高效,在子查询中我只选择我们需要的行 - SUBPART 为 C 或 K 的行。我们不需要查看其他行。

WITH 子句仅用于测试 - 删除它,并在查询中使用您的实际表名和列名。

with
  test_data (pk, facility_id, reporting_year, subpart, co2e) as (
    select 335, 10, 2020, 'C', 10 from dual union all
    select 440, 11, 2020, 'K', 20 from dual union all
    select 482, 10, 2020, 'K', 40 from dual union all
    select 106, 10, 2020, 'K', 40 from dual union all
    select 476, 11, 2020, 'C', 30 from dual
  )
-- end of test data; actual query begins below this line
select facility_id, reporting_year, c, k
from   (
         select facility_id, reporting_year, subpart, co2e
         from   test_data
         where  subpart in ('C', 'K')
       )
pivot  (sum(co2e) for subpart in ('C' as c, 'K' as k))
order  by facility_id, reporting_year  --  or whatever is needed
;

FACILITY_ID REPORTING_YEAR          C          K
----------- -------------- ---------- ----------
         10           2020         10         80
         11           2020         30         20

注意 - 完全取消 PIVOT 并使用条件聚合“旋转”旧方法可能更简单(也更有效)(在引入 PIVOT 运算符之前完成旋转的方式)。像这样的:

select facility_id, reporting_year,
       sum(case subpart when 'C' then co2e end) as c,
       sum(case subpart when 'K' then co2e end) as k
from   test_data
group  by facility_id, reporting_year
order  by facility_id, reporting_year
;

【讨论】:

  • 嗨,谢谢。很高兴知道继续前进 - 我喜欢没有枢轴的更简单的方法。以后我会尝试使用它来运行
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-18
  • 1970-01-01
  • 2015-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-20
相关资源
最近更新 更多