Home > Enterprise >  get item with GREATEST amount of purchases show all customers
get item with GREATEST amount of purchases show all customers

Time:01-31

I have a query, which finds the GREATEST amount of which item was purchased. It appears to be working fine (see below).

I have two questions, first is there a better way to rewrite this query without using 2 CTE and not displaying the value of rnk in the output.

Secondly, in another query how can I show the product_id, product_name, price, customer_id, first_name, last_name, total_qty, total_amt for this item. I am expecting to see 3 rows based on the data provided.


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(
    ORDER_ID NUMBER GENERATED BY DEFAULT AS IDENTITY (START WITH 1) NOT NULL,
    CUSTOMER_ID NUMBER, 
    PRODUCT_ID NUMBER, 
    QUANTITY NUMBER, 
   PURCHASE_DATE TIMESTAMP
);

INSERT  INTO purchases
(CUSTOMER_ID, PRODUCT_ID, QUANTITY, PURCHASE_DATE) 
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 2, 102, 3,TIMESTAMP '2022-12-26 11:41:25'   NUMTODSINTERVAL ( LEVEL * 2, 'DAY') FROM  dual CONNECT BY  LEVEL <= 6 UNION ALL
SELECT 3, 101,1, TIMESTAMP '2022-12-21 09:54:48' FROM DUAL UNION ALL
SELECT 3, 102,1, TIMESTAMP '2022-12-27 19:04:18' FROM DUAL UNION ALL
SELECT 3, 102, 4,TIMESTAMP '2022-12-22 21:44:35'   NUMTODSINTERVAL ( LEVEL * 2, 'DAY') FROM    dual
CONNECT BY  LEVEL <= 15 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;

ALTER TABLE customers 
ADD CONSTRAINT customers_pk PRIMARY KEY (customer_id);

ALTER TABLE items 
ADD CONSTRAINT items_pk PRIMARY KEY (product_id);

ALTER TABLE purchases 
ADD CONSTRAINT order_pk PRIMARY KEY (order_id);

ALTER TABLE purchases ADD CONSTRAINT customers_fk FOREIGN KEY (customer_id) REFERENCES customers(customer_id);

ALTER TABLE purchases ADD CONSTRAINT items_fk FOREIGN KEY (PRODUCT_ID) REFERENCES items(product_id);

/* 
get item with GREATEST amount of purchases 
*/
 with cte as
      (SELECT
            i.product_id,
            i.product_name,
            i.price,
            SUM (p.quantity) AS total_qty,
      SUM (p.quantity * i.price)         AS total_amt
      FROM    purchases  p
      JOIN    customers  c  ON  p.customer_id = c.customer_id
      JOIN    items   i  ON  p.product_id  = i.product_id
     GROUP BY
        i.product_id,
        i.product_name,
        i.price, p.quantity),
   cte2 as
     (SELECT product_id,
         product_name,
         price,
                      total_qty,
         total_amt,
         RANK() OVER (ORDER BY total_amt DESC) rnk 
    FROM   cte)
   SELECT *
   FROM   cte2
   WHERE  rnk = 1;

PRODUCT_ID  PRODUCT_NAME    PRICE   TOTAL_QTY   TOTAL_AMT   RNK
102 White Shirt 10.99   80  879.2   1

CodePudding user response:

You could create a cte (or a subquery) that will give you all the data you need to get either greatest amount of all products or greatest per product:

SELECT 
    i.PRODUCT_ID, i.PRODUCT_NAME, i.PRICE, 
    c.CUSTOMER_ID, c.FIRST_NAME, c.LAST_NAME, 
    Sum(p.QUANTITY) "TOTAL_QTY", Sum(p.QUANTITY * i.PRICE) "TOTAL_AMT",
    RANK() OVER (PARTITION BY i.PRODUCT_ID ORDER BY i.PRODUCT_ID, Sum(p.QUANTITY * i.PRICE) DESC) "PRODUCT_RNK",
    RANK() OVER (ORDER BY Sum(p.QUANTITY * i.PRICE) DESC) "TOTAL_RNK"
FROM 
    items i
INNER JOIN
    purchases p ON(p.PRODUCT_ID = i.PRODUCT_ID)
INNER JOIN
    customers c ON(c.CUSTOMER_ID = p.CUSTOMER_ID)
GROUP BY
    i.PRODUCT_ID, i.PRODUCT_NAME, i.PRICE, 
    c.CUSTOMER_ID, c.FIRST_NAME, c.LAST_NAME
ORDER BY
    i.PRODUCT_ID, Sum(p.QUANTITY * i.PRICE) DESC

SubQuery or CTE Result:
PRODUCT_ID PRODUCT_NAME      PRICE CUSTOMER_ID FIRST_NAME LAST_NAME  TOTAL_QTY  TOTAL_AMT PRODUCT_RNK  TOTAL_RNK
---------- ------------ ---------- ----------- ---------- --------- ---------- ---------- ----------- ----------
       100 Black Shoes       79.99           1 Faith      Mazzarone          1      79.99           1          6 
       101 Brown Pants      111.99           2 Lisa       Saladino           4     447.96           1          2 
       101 Brown Pants      111.99           1 Faith      Mazzarone          3     335.97           2          4 
       101 Brown Pants      111.99           3 Micheal    Palmice            2     223.98           3          5 
       102 White Shirt       10.99           3 Micheal    Palmice           82     901.18           1          1 
       102 White Shirt       10.99           2 Lisa       Saladino          36     395.64           2          3

with this dataset you can get the results like below:

-- if it is a CTE named cte:
SELECT    *  FROM  cte WHERE PRODUCT_RNK = 1
PRODUCT_ID PRODUCT_NAME      PRICE CUSTOMER_ID FIRST_NAME LAST_NAME  TOTAL_QTY  TOTAL_AMT PRODUCT_RNK  TOTAL_RNK
---------- ------------ ---------- ----------- ---------- --------- ---------- ---------- ----------- ----------
       100 Black Shoes       79.99           1 Faith      Mazzarone          1      79.99           1          6 
       101 Brown Pants      111.99           2 Lisa       Saladino           4     447.96           1          2 
       102 White Shirt       10.99           3 Micheal    Palmice           82     901.18           1          1

OR
SELECT    *  FROM  cte WHERE TOTAL_RNK = 1
PRODUCT_ID PRODUCT_NAME      PRICE CUSTOMER_ID FIRST_NAME LAST_NAME  TOTAL_QTY  TOTAL_AMT PRODUCT_RNK  TOTAL_RNK
---------- ------------ ---------- ----------- ---------- --------- ---------- ---------- ----------- ----------
       102 White Shirt       10.99           3 Micheal    Palmice           82     901.18           1          1
  • Related