I am trying to use the ROLLUP command to group my data by year/week, customer_id but I can't seem to get it to work.
Below is my sample data and my attempt. Can someone show me how to make this work
ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'DD-MON-YYYY HH24:MI:SS.FF';
ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY HH24:MI:SS';
CREATE TABLE customers
(CUSTOMER_ID, FIRST_NAME, LAST_NAME) AS
SELECT 1, 'Faith', 'Mazzarone' FROM DUAL UNION ALL
SELECT 2, 'Lisa', 'Saladino' FROM DUAL UNION ALL
SELECT 3, 'Micheal', 'Palmice' FROM DUAL UNION ALL
SELECT 4, 'Jerry', 'Torchiano' FROM DUAL;
CREATE TABLE items
(PRODUCT_ID, PRODUCT_NAME, PRICE) AS
SELECT 100, 'Black Shoes', 79.99 FROM DUAL UNION ALL
SELECT 101, 'Brown Pants', 111.99 FROM DUAL UNION ALL
SELECT 102, 'White Shirt', 10.99 FROM DUAL;
CREATE TABLE purchases
(CUSTOMER_ID, PRODUCT_ID, QUANTITY, PURCHASE_DATE) AS
SELECT 1, 101, 3, TIMESTAMP'2022-10-11 09:54:48' FROM DUAL UNION ALL
SELECT 1, 100, 1, TIMESTAMP '2022-10-12 19:04:18' FROM DUAL UNION ALL
SELECT 2, 101,1, TIMESTAMP '2022-10-11 09:54:48' FROM DUAL UNION ALL
SELECT 2, 101, 3, TIMESTAMP '2022-10-17 19:34:58' FROM DUAL UNION ALL
SELECT 2, 102, 3,TIMESTAMP '2022-12-06 11:41:25' NUMTODSINTERVAL ( LEVEL * 2, 'DAY') FROM dual CONNECT BY LEVEL <= 6 UNION ALL
SELECT 3, 101,1, TIMESTAMP '2022-12-11 09:54:48' FROM DUAL UNION ALL
SELECT 3, 102,1, TIMESTAMP '2022-12-17 19:04:18' FROM DUAL UNION ALL
SELECT 3, 102, 4,TIMESTAMP '2022-12-12 21:44:35' NUMTODSINTERVAL ( LEVEL * 2, 'DAY') FROM dual
CONNECT BY LEVEL <= 5;
SELECT
p.customer_id,
c.first_name,
c.last_name,
sum(p.quantity * i.price) total_amt
FROM purchases p,
items i,
customers c
WHERE p.customer_id = c.customer_id
GROUP BY ROLLUP (to_char(p.purchase_date, 'YYYY/IW'),(p.customer_id)));
CodePudding user response:
To me, it looks as
SQL> SELECT p.customer_id,
2 c.first_name,
3 c.last_name,
4 TO_CHAR (p.purchase_date, 'YYYY/IW') year_week,
5 SUM (p.quantity * i.price) total_amt
6 FROM purchases p, items i, customers c
7 WHERE p.customer_id = c.customer_id
8 GROUP BY c.first_name,
9 c.last_name,
10 p.customer_id,
11 ROLLUP (TO_CHAR (p.purchase_date, 'YYYY/IW'))
12 ORDER BY customer_id, year_week;
CUSTOMER_ID FIRST_N LAST_NAME YEAR_WE TOTAL_AMT
----------- ------- --------- ------- ----------
1 Faith Mazzarone 2022/41 811,88
1 Faith Mazzarone 811,88
2 Lisa Saladino 2022/41 202,97
2 Lisa Saladino 2022/42 608,91
2 Lisa Saladino 2022/49 1217,82
2 Lisa Saladino 2022/50 2435,64
2 Lisa Saladino 4465,34
3 Micheal Palmice 2022/49 202,97
3 Micheal Palmice 2022/50 2638,61
3 Micheal Palmice 2022/51 1623,76
3 Micheal Palmice 4465,34
11 rows selected.
SQL>
CodePudding user response:
You have not included a JOIN
condition for the items
table and, since the first_name
and last_name
are dependent on the customer_id
then, you can aggregate the name components:
SELECT p.customer_id,
CASE
WHEN p.customer_id IS NULL
THEN NULL
ELSE MAX(c.first_name)
END AS first_name,
CASE
WHEN p.customer_id IS NULL
THEN NULL
ELSE MAX(c.last_name)
END AS last_name,
to_char(p.purchase_date, 'YYYY/IW') AS week,
sum(p.quantity * i.price) total_amt
FROM purchases p
INNER JOIN customers c
ON p.customer_id = c.customer_id
INNER JOIN items i
ON p.product_id = i.product_id
GROUP BY
ROLLUP(
p.customer_id,
to_char(p.purchase_date, 'YYYY/IW')
);
Outputs:
CUSTOMER_ID | FIRST_NAME | LAST_NAME | WEEK | TOTAL_AMT |
---|---|---|---|---|
1 | Faith | Mazzarone | 2022/41 | 415.96 |
2 | Lisa | Saladino | 2022/41 | 111.99 |
2 | Lisa | Saladino | 2022/42 | 335.97 |
2 | Lisa | Saladino | 2022/49 | 65.94 |
2 | Lisa | Saladino | 2022/50 | 131.88 |
3 | Micheal | Palmice | 2022/49 | 111.99 |
3 | Micheal | Palmice | 2022/50 | 142.87 |
3 | Micheal | Palmice | 2022/51 | 87.92 |
1 | Faith | Mazzarone | null | 415.96 |
2 | Lisa | Saladino | null | 645.78 |
3 | Micheal | Palmice | null | 342.78 |
null | null | null | null | 1404.52 |
and reversing the ROLLUP
:
SELECT p.customer_id,
CASE
WHEN p.customer_id IS NULL
THEN NULL
ELSE MAX(c.first_name)
END AS first_name,
CASE
WHEN p.customer_id IS NULL
THEN NULL
ELSE MAX(c.last_name)
END AS last_name,
to_char(p.purchase_date, 'YYYY/IW') AS week,
sum(p.quantity * i.price) total_amt
FROM purchases p
INNER JOIN customers c
ON p.customer_id = c.customer_id
INNER JOIN items i
ON p.product_id = i.product_id
GROUP BY
ROLLUP(
to_char(p.purchase_date, 'YYYY/IW'),
p.customer_id
);
Outputs:
CUSTOMER_ID | FIRST_NAME | LAST_NAME | WEEK | TOTAL_AMT |
---|---|---|---|---|
1 | Faith | Mazzarone | 2022/41 | 415.96 |
2 | Lisa | Saladino | 2022/41 | 111.99 |
2 | Lisa | Saladino | 2022/42 | 335.97 |
2 | Lisa | Saladino | 2022/49 | 65.94 |
2 | Lisa | Saladino | 2022/50 | 131.88 |
3 | Micheal | Palmice | 2022/49 | 111.99 |
3 | Micheal | Palmice | 2022/50 | 142.87 |
3 | Micheal | Palmice | 2022/51 | 87.92 |
null | null | null | 2022/41 | 527.95 |
null | null | null | 2022/42 | 335.97 |
null | null | null | 2022/49 | 177.93 |
null | null | null | 2022/50 | 274.75 |
null | null | null | 2022/51 | 87.92 |
null | null | null | null | 1404.52 |