Home > Back-end >  Find the 3rd top selling item postgres
Find the 3rd top selling item postgres

Time:09-22

I have a transaction table, I want to get the product ID of the record which is ranked 3rd highest for sales. Please note there there can be multiple transactions for an item and one transaction can have multiple qty. so i am wanting to find which product id has the 3rd highest qty.

I think i need to use something like rank, but my query returns ranks weirdly, not sure whats wrong.

select distinct t.product_id,
  sum(t.qty) over (partition by t.product_id) qty, 
  rank() over(partition by t.product_id order by t.qty desc) rnk
from transaction t
order by rnk`

CREATE TABLE IF NOT EXISTS "transaction"
  (DATE_ID             BIGINT NOT NULL,
   STORE_ID            INT NOT NULL,
   TRANSACTION_TYPE_ID CHAR(1) NOT NULL,
   PRODUCT_ID          INT NOT NULL,
   QTY                 INT NOT NULL);

INSERT INTO "transaction"
  (DATE_ID, STORE_ID, TRANSACTION_TYPE_ID, PRODUCT_ID, QTY)
VALUES
  (1, 1, 'A', 1, 2),
  (1, 1, 'B', 1, 1),
  (1, 2, 'A', 4, 1),
  (1, 6, 'A', 3, 1),
  (1, 1, 'A', 1, 1),
  (2, 1, 'B', 1, 1),
  (2, 1, 'A', 1, 1),
  (2, 2, 'A', 2, 5),
  (3, 2, 'A', 2, 7),
  (3, 3, 'A', 2, 1),
  (3, 3, 'B', 1, 15),
  (3, 3, 'A', 1, 1),
  (4, 4, 'A', 1, 1),
  (4, 4, 'A', 1, 5),
  (4, 4, 'A', 1, 11),
  (4, 5, 'A', 3, 2),
  (4, 6, 'A', 3, 1),
  (4, 6, 'A', 3, 1),
  (4, 6, 'B', 2, 1),
  (5, 2, 'A', 2, 2),
  (5, 2, 'B', 1, 1),
  (5, 2, 'A', 2, 1),
  (5, 2, 'A', 4, 1),
  (5, 2, 'A', 5, 1),
  (6, 2, 'B', 4, 1),
  (6, 2, 'A', 6, 1),
  (6, 3, 'A', 3, 5),
  (7, 3, 'A', 2, 7),
  (7, 4, 'A', 2, 1),
  (7, 4, 'B', 2, 15),
  (7, 4, 'A', 2, 1),
  (7, 5, 'A', 2, 1),
  (7, 5, 'A', 2, 5),
  (7, 5, 'A', 2, 11),
  (7, 6, 'A', 2, 2),
  (7, 1, 'A', 2, 1),
  (8, 1, 'A', 2, 1),
  (8, 1, 'B', 2, 1),
  (8, 3, 'A', 3, 2),
  (9, 3, 'B', 3, 1),
  (9, 3, 'A', 3, 1),
  (9, 3, 'A', 3, 1),
  (9, 3, 'A', 3, 1),
  (10, 3, 'B', 3, 1),
  (10, 3, 'A', 3, 1),
  (10, 4, 'A', 4, 5),
  (10, 4, 'A', 4, 7),
  (10, 5, 'A', 5, 1),
  (10, 5, 'B', 5, 15),
  (10, 5, 'A', 5, 1),
  (10, 6, 'A', 6, 1),
  (10, 6, 'A', 6, 5),
  (10, 6, 'A', 6, 11),
  (10, 1, 'A', 1, 2),
  (10, 2, 'A', 2, 1),
  (11, 2, 'A', 2, 1),
  (11, 2, 'B', 2, 1),
  (11, 3, 'A', 5, 2),
  (11, 3, 'B', 5, 1),
  (11, 3, 'A', 5, 1),
  (12, 3, 'A', 5, 1),
  (12, 3, 'A', 5, 1)

CodePudding user response:

Yet another option is:

  • aggregating the "qty" values per "product_id" (SUM(qty) GROUP BY product_id)
  • extracting a ranking value for each product_id summed quantities (DENSE_RANK() OVER(ORDER BY SUM(qty) DESC))
  • ordering your output rows with respect to when this ranking value equals 3 (DENSE_RANK() ... = 3)
  • keeping only the first row given your ordering (FETCH FIRST 1 ROWS WITH TIES )
SELECT product_id
FROM "transaction"
GROUP BY product_id
ORDER BY DENSE_RANK() OVER(ORDER BY SUM(qty) DESC) = 3 DESC
FETCH FIRST 1 ROWS WITH TIES 

Check the demo here.

CodePudding user response:

select  product_id
from    (
        select   product_id
                ,dense_rank() over(order by sum(qty)) as d_rnk
        from     transaction
        group by product_id 
        ) t
where   d_rnk = 3
product_id
5

Fiddle

  • Related