带有其他(非聚合)列的Oracle SQL xml pivot

时间:2018-01-16 18:30:24

标签: sql oracle pivot

我正在寻找一种在xml数据透视查询中包含非聚合值的方法。我的代码如下所示:

select * from (
select country, month from travel
where <parameters, as far as i know irrelevant to the discussion>
pivot xml (
count(month) travellers,
for country in (select country from table_a where <parameters>)
)

查询表格,其中每一行代表一个人旅行,这样月份的数量将返回该月份的旅行人数。

此查询返回以下xml:

<PivotSet>
    <item>
        <column name = "COUNTRY">AE</column>
        <column name = "TRAVELLERS">1</column>
    </item>
    <item>
        <column name = "COUNTRY">AL</column>
        <column name = "TRAVELLERS">1</column>
    </item>
    <item>
        <column name = "COUNTRY">BE</column>
        <column name = "TRAVELLERS">2</column>
    </item>
    <item>
    ...
    </item>
</PivotSet>

我想要的是获得b和c的非聚合值,我希望它们看起来像:

select * from (
select country, month from travel
where <parameters, irrelevant to the discussion>
pivot xml (
count(month) travellers,
for country, month in (select country, month from table_a where <parameters>)
)

但这不起作用,因为pivot似乎只允许一列的非聚合值。

我希望看到以下xml返回:

<PivotSet>
    <item>
        <column name="MONTH">JANUARY</column>
        <column name = "COUNTRY">AE</column>
        <column name = "TRAVELLERS">1</column>
    </item>
    <item>
        <column name="MONTH">FEBRUARY</column>
        <column name = "COUNTRY">AL</column>
        <column name = "TRAVELLERS">1</column>
    </item>
    <item>
        <column name="MONTH">MARCH</column>
        <column name = "COUNTRY">BE</column>
        <column name = "TRAVELLERS">2</column>
    </item>
    <item>
    ...
    </item>
</PivotSet>

我有什么选择让这项工作成功?我误解了枢轴功能是如何工作的吗?

1 个答案:

答案 0 :(得分:0)

就我在问题中的代码片段中所看到的,忽略我认为是你引入的错误所引发的错误;你只需要在你正在转动的两列上添加括号:

select *
from (
  select country, month from travel
  where <parameters, as far as i know irrelevant to the discussion>
)
pivot xml (
  count(*) travellers
  for (country, month) in (select country from table_a where <parameters>)
)

The pivot clause syntax diagram表示您可以在括号中使用单个表达式或逗号分隔的表达式列表。没有括号,它不会期望第二个表达式(, month)并抛出“ORA-01738:缺少IN关键字”,因为 它预期接下来要看到的内容。

使用CTE进行演示,并假设您为了简单起见,从同一张表中获取了不同的月份/国家/地区:

-- CTE for dummy data
with travel (country, month) as (
  select 'US', date '2017-01-01' from dual connect by level <= 3
  union all select 'US', date '2017-02-01' from dual connect by level <= 1
  union all select 'France', date '2017-01-01' from dual connect by level <= 1
  union all select 'France', date '2017-02-01' from dual connect by level <= 5
  union all select 'Spain', date '2017-01-01' from dual connect by level <= 5
  union all select 'Spain', date '2017-02-01' from dual connect by level <= 2
)
-- actual query
select xmlserialize(document country_month_xml indent size=2)
from (
  select country, month from travel
)
pivot xml (
  count(*) travellers
  for (country, month) in (select distinct country, month from travel)
);

得到:

<PivotSet>
  <item>
    <column name="COUNTRY">France</column>
    <column name="MONTH">2017-01-01</column>
    <column name="TRAVELLERS">1</column>
  </item>
  <item>
    <column name="COUNTRY">France</column>
    <column name="MONTH">2017-02-01</column>
    <column name="TRAVELLERS">5</column>
  </item>
  <item>
    <column name="COUNTRY">Spain</column>
    <column name="MONTH">2017-01-01</column>
    <column name="TRAVELLERS">5</column>
  </item>
  <item>
    <column name="COUNTRY">Spain</column>
    <column name="MONTH">2017-02-01</column>
    <column name="TRAVELLERS">2</column>
  </item>
  <item>
    <column name="COUNTRY">US</column>
    <column name="MONTH">2017-01-01</column>
    <column name="TRAVELLERS">3</column>
  </item>
  <item>
    <column name="COUNTRY">US</column>
    <column name="MONTH">2017-02-01</column>
    <column name="TRAVELLERS">1</column>
  </item>
</PivotSet>

我添加了一个XMLSerialize调用只是为了让它更具可读性......