【问题标题】:Oracle SQL - Conditional aggregation pivot with multiple headerOracle SQL - 具有多个标头的条件聚合透视
【发布时间】:2018-05-30 23:00:45
【问题描述】:

这个问题是我之前的post 的增强版,希望我能在这里得到一些帮助。我有下表/查看示例或虚拟数据:
表/视图名称:CUST_HOTEL_VIEW

+----+----------------+---------------+---------------+--------+---------------+
| ID |    Customer    |     Hotel     | Booked_Status | Budget | Booked_Amount |
+----+----------------+---------------+---------------+--------+---------------+
|  1 | John Smith     | Beverly Hills | Booked        |   2000 |           500 |
|  2 | John Smith     | Royal Palms   | Cancelled     |   3000 |               |
|  3 | Marilyn Lawson | Beverly Hills |               |    500 |               |
|  4 | John Smith     | Ritz-Carlton  |               |    250 |               |
|  5 | Marilyn Lawson | Royal Palms   |               |    700 |               |
|  6 | Sarah Elliot   | Royal Palms   | Cancelled     |   1500 |               |
|  7 | Sarah Elliot   | Ritz-Carlton  | Booked        |   2000 |          1500 |
|  8 | Sarah Elliot   | Royal Palms   | Booked        |   2500 |          1000 |
+----+----------------+---------------+---------------+--------+---------------+

需要帮助才能获得具有多个标题的输出,即获取客户数量和每家酒店的预算总和(以下是 excel 数据透视表的输出):

我正在使用 Oracle 12c R1 db,如果我使用条件聚合进行查询会有所帮助;因为我发现这更简单,更容易理解。

我尝试了以下查询来获取计数和预订金额:

SELECT COALESCE(CUSTOMER, 'Grand Total') as " " ,
       (case when COUNT(booked_status) != 0 then count(booked_status) else null end) as "# Booked",
sum(case when booked_status = 'Booked' THEN booking_amount ELSE null END) as "Booked Amount"
FROM CUST_HOTEL_VIEW
GROUP BY ROLLUP(CUSTOMER)
order by CUSTOMER

并得到以下输出:

+--------------+----------+---------------+
|              | # Booked | Booked Amount |
+--------------+----------+---------------+
| John Smith   |        1 |           500 |
| Sarah Elliot |        2 |          2500 |
| Grand Total  |        3 |          3000 |
+--------------+----------+---------------+

但无法通过合并的标头获得输出。

感谢您对此提供的任何帮助。

谢谢,
里查

更新: 在下面添加最终输出表部分: 最终输出表:

+--------------+---------------+--------+-------------+--------+--------------+--------+-------------+------+
|   CUSTOMER   |      Beverly Hills     |      Royal Palms     |      Ritz-Carlton     |      Grand Total   |
+--------------+---------------+--------+-------------+--------+--------------+--------+-------------+------+
|              | Count         | Sum    | Count       | Sum    | Count        | Sum    | Count       | Sum  |
+--------------+---------------+--------+-------------+--------+--------------+--------+-------------+------+
| Sarah Elliot | 0             | (null) | 1           | 2500   | 1            | 2000   | 2           | 4500 |
| John Smith   | 1             | 2000   | 0           | (null) | 0            | (null) | 1           | 2000 |
| Grand Total  | 1             | 2000   | 1           | 2500   | 1            | 2000   | 3           | 6500 |
+--------------+---------------+--------+-------------+--------+--------------+--------+-------------+------+

【问题讨论】:

  • 在 SQL 中,您决定在编写查询时填写哪些列。因为您的结果集中有 15 家不同的酒店,所以不可能获得 15 列。我用一个表格计算程序完成这样的任务
  • F.e. Excel 数据透视表
  • @am2,感谢您的及时回复。我很感激。假设表只有 3 或 4 家酒店,从这个意义上说,用 sql 查询仍然不可能吗?我想知道 SQL 如何通过分组来实现多行标题。如果查询适用于我提供的示例数据,那对我来说已经足够了。

标签: sql oracle header pivot


【解决方案1】:

从问题的描述中我无法推断出究竟是什么要求,但在我看来,您正在寻找类似的东西:


演示:http://sqlfiddle.com/#!4/dbd49/7

SELECT *
FROM (
  SELECT CUSTOMER, HOTEL, BUDGET
  FROM Table1
  WHERE BOOKED_STATUS = 'Booked'
)
PIVOT (
  count(*) as cnt, sum(BUDGET) as budget
  FOR HOTEL IN ('Beverly Hills','Royal Palms','Ritz-Carlton')
 )

|     CUSTOMER | 'Beverly Hills'_CNT | 'Beverly Hills'_BUDGET | 'Royal Palms'_CNT | 'Royal Palms'_BUDGET | 'Ritz-Carlton'_CNT | 'Ritz-Carlton'_BUDGET |
|--------------|---------------------|------------------------|-------------------|----------------------|--------------------|-----------------------|
| Sarah Elliot |                   0 |                 (null) |                 1 |                 2500 |                  1 |                  2000 |
|   John Smith |                   1 |                   2000 |                 0 |               (null) |                  0 |                (null) |

【讨论】:

  • 感谢您的回复。如果我的问题令人困惑,我很抱歉。您建议的答案非常接近,但我希望标题合并。由于我无法在评论中发布表格。我正在“FINAL TABLE OUTPUT”部分下更新 OP
  • 这在普通 SQL 中是不可能做到的,您需要在应用程序的表示层(无论是什么 - java、c#、excel 等),而不是在数据库端做到这一点..
  • 感谢您的反馈和回答。我很感激。您能否告诉我是否可以在此行中使用子查询:FOR HOTEL IN ('Beverly Hills','Royal Palms','Ritz-Carlton')。我尝试了子查询并收到错误
  • 不,不能使用子查询,pivot 是静态 SQL。您可以在 XML PIVOT 中使用子查询,请参阅这篇文章:oracle.com/technetwork/articles/sql/11g-pivot-097235.html,但这会生成 XML 结果,而不是类似表格的结果集。也可以使用动态 SQL 来生成动态查询,但这是一个很大的话题。
猜你喜欢
  • 2016-06-10
  • 1970-01-01
  • 2013-01-19
  • 2020-10-02
  • 1970-01-01
  • 2014-12-12
  • 1970-01-01
  • 2022-11-29
  • 1970-01-01
相关资源
最近更新 更多