Oracle SQL - сводить строки таблицы в столбец и использовать подзапрос в сводной таблице - PullRequest
0 голосов
/ 26 мая 2018

Я работаю на Oracle 12c R1 db и имею примерное представление с образцами данных, как показано ниже:
Имя представления: CUST_HOTEL_VIEW

+----------------+---------------+---------------+
|    Customer    |     Hotel     | Booked Status |
+----------------+---------------+---------------+
| John Smith     | Beverly Hills | Booked        |
| John Smith     | Royal Palms   |               |
| Marilyn Lawson | Beverly Hills |               |
| John Smith     | Ritz-Carlton  |               |
| Marilyn Lawson | Royal Palms   |               |
| Sarah Elliot   | Royal Palms   |               |
| Sarah Elliot   | Ritz-Carlton  | Booked        |
| Sarah Elliot   | Royal Palms   | Booked        |
+----------------+---------------+---------------+

Из данных выше я пытаюсьчтобы получить вывод ниже сводной информации, указав общий итог строки, итоговую сумму столбца и количество отелей, забронированных для каждого клиента:

+----------------+-------------+---------------+--------------+-------------+----------+
|    Customer    | Royal Palms | Beverly Hills | Ritz-Carlton | Grand Total | # Booked |
+----------------+-------------+---------------+--------------+-------------+----------+
| John Smith     |           1 |             1 |            1 |           3 |        1 |
| Marilyn Lawson |           1 |             1 |              |           2 |        - |
| Sarah Elliot   |           2 |               |            1 |           3 |        2 |
| Grand Total    |           4 |             2 |            2 |           8 |        3 |
+----------------+-------------+---------------+--------------+-------------+----------+

Я попытался выполнить запрос ниже для создания сводных данных

SELECT * FROM
(
  SELECT CUSTOMER, HOTEL
  FROM CUST_HOTEL_VIEW
)
PIVOT
(
  COUNT(HOTEL)
  FOR HOTEL IN ('Royal Palms' as "Royal Palms",'Beverly Hills' as "Beverly Hills",'Ritz-Carlton' as "Ritz-Carlton")
)
ORDER BY CUSTOMER

Я хотел бызнать:
1. Как включить общую сумму строки
2. Как включить общую сумму столбца
3. Как включить количество забронированных отелей и
3. Можно ли написать подзапрос внутриPIVOT FOR HOTEL В пункте.(Я пробовал подзапрос, но получаю ошибку)

Я ценю любую помощь по этому вопросу.

Спасибо,
Рича

Ответы [ 3 ]

0 голосов
/ 26 мая 2018

Попробуйте это:

1) Для включения общей суммы строки union можно использовать

2) Для включения общей суммы столбца sum функция используется в первой таблице (p1): тот же код, написанный вами с помощью функции суммы

3) Чтобы включить количество забронированных отелей, требуется another pivot, то есть вторая таблица (p2)


Шаг 1: Составьте таблицу p1 с клиентом, различными отелями и их общим итогом (общее количество столбцов)


create table p1 as
SELECT customer,RoyalPalms,BeverlyHills,RitzCarlton,sum(RoyalPalms + BeverlyHills + RitzCarlton) as GrandTotal  FROM
(
  SELECT CUSTOMER, HOTEL
  FROM CUST
)
PIVOT
( COUNT(HOTEL)
  FOR HOTEL IN ('Royal Palms' as RoyalPalms,'Beverly Hills' as BeverlyHills,
                'Ritz-Carlton' as RitzCarlton) ) 
group by customer,RoyalPalms,BeverlyHills,RitzCarlton
order by customer;                

Шаг 2: Составьте таблицу p2 с клиентоми забронированные отели


create table p2 as
SELECT *  FROM
(
  SELECT customer,booked_status
  FROM cust
)
pivot 
 ( count(booked_status) 
  for booked_status in ('Booked' as Booked));

Step3: объединить таблицы p1 и p2

Step4: для итоговой строки взятьобъединение таблицы, созданной на шаге 3, с итогами строк, рассчитанными с помощью функции суммирования


(SELECT a.*,b.booked
 from p1 a 
 left join
 p2 b
 on a.customer = b.customer) 
union all
SELECT 'GrandTotal', Sum(RoyalPalms),sum(BeverlyHills),sum(RitzCarlton),
sum(GrandTotal),sum(booked) From test;

Вывод:

+----------------+-------------+---------------+--------------+-------------+----------+
|    Customer    | Royal Palms | Beverly Hills | Ritz-Carlton | Grand Total | # Booked |
+----------------+-------------+---------------+--------------+-------------+----------+
| John Smith     |           1 |             1 |            1 |           3 |        1 |
| Marilyn Lawson |           1 |             1 |              |           2 |        - |
| Sarah Elliot   |           2 |               |            1 |           3 |        2 |
| Grand Total    |           4 |             2 |            2 |           8 |        3 |
+----------------+-------------+---------------+--------------+-------------+----------+

Сообщите мнев случае необходимости дальнейших запросов / объяснений.

0 голосов
/ 26 мая 2018

Просто используйте условное агрегирование:

SELECT COALESCE(customer, 'Grand Total') as customer,
       SUM(CASE WHEN Hotel = 'Royal Palms' THEN 1 ELSE 0 END) as "Royal Palms",
       SUM(CASE WHEN Hotel = 'Beverly Hills' THEN 1 ELSE 0 END) as "Beverly Hills",       
       SUM(CASE WHEN Hotel = 'Ritz-Carlton' THEN 1 ELSE 0 END) as "Ritz-Carlton" ,
       COUNT(*) as "Grand Total",
       COUNT(Booked_Status) as "Num Booked"
FROM CUST_HOTEL_VIEW
GROUP BY ROLLUP(CUSTOMER)
ORDER BY CUSTOMER;

Условное агрегирование гораздо более гибкое, чем pivot.Лично я не вижу причин для синтаксиса pivot: он хорошо выполняет одну задачу, но не является строительным блоком, как традиционные операторы SQL.

ROLLUP() также весьма полезен.Вы также можете использовать:

GROUP BY GROUPING SETS ( (CUSTOMER), () )
0 голосов
/ 26 мая 2018

Возможно, существует более простое решение, но оно должно помочь вам начать работу -

WITH A AS (
    SELECT
        *
    FROM
        (
            SELECT
                CUSTOMER,
                HOTEL,
                BOOKED_STATUS
            FROM
                TABLE1
        )
            PIVOT ( COUNT ( HOTEL )
                FOR HOTEL
                IN ( 'ROYAL PALMS' AS "ROYAL PALMS",'BEVERLY HILLS' AS "BEVERLY HILLS",'RITZ-CARLTON' AS "RITZ-CARLTON" )
            )
),B AS (
    SELECT
        CUSTOMER,
        "ROYAL PALMS",
        "BEVERLY HILLS",
        "RITZ-CARLTON",
        SUM("ROYAL PALMS" + "BEVERLY HILLS" + "RITZ-CARLTON") AS "GRAND TOTAL"
    FROM
        A
    GROUP BY
        CUSTOMER,
        "ROYAL PALMS",
        "BEVERLY HILLS",
        "RITZ-CARLTON"
),C AS (
    SELECT
        CUSTOMER,
        SUM("ROYAL PALMS" + "BEVERLY HILLS" + "RITZ-CARLTON") AS NBOOK
    FROM
        A
    WHERE
        BOOKED_STATUS IS NOT NULL
    GROUP BY
        CUSTOMER
),D AS (
    SELECT
        B.CUSTOMER,
        SUM("ROYAL PALMS") AS "ROYAL PALMS",
        SUM("BEVERLY HILLS") AS "BEVERLY HILLS",
        SUM("RITZ-CARLTON") AS "RITZ-CARLTON",
        SUM("GRAND TOTAL") AS "GRAND TOTAL",
        NVL(C.NBOOK,0) AS NBOOK
    FROM
        B,
        C
    WHERE
        B.CUSTOMER   = C.CUSTOMER (+)
    GROUP BY
        B.CUSTOMER,
        NVL(C.NBOOK,0)
) SELECT
    *
FROM
    D
UNION
SELECT
    'GRAND TOTAL' AS CUSTOMER,
    SUM("ROYAL PALMS"),
    SUM("BEVERLY HILLS"),
    SUM("RITZ-CARLTON"),
    SUM("GRAND TOTAL") AS "GRAND TOTAL",
    SUM(NBOOK) AS NBOOK
FROM
    D
ORDER BY 5,1;

Вывод -

"CUSTOMER","ROYAL PALMS","BEVERLY HILLS","RITZ-CARLTON","GRAND TOTAL","NBOOK"
"MARILYN LAWSON",1,1,0,2,0
"JOHN SMITH",1,1,1,3,1
"SARAH ELLIOT",2,0,1,3,2
"GRAND TOTAL",4,2,2,8,3
...