Home > Mobile >  Window function query in MySQL
Window function query in MySQL

Time:05-26

We have columns Date, CID, Budget. We want to create a column Budget_rank which gives us result as: Observe that the resultant table looks sorted on date first and then whichever same Budget values were there, they got the same rank

Expected Output:

Date       | CID | Budget | Budget_rank 
---------------------------------
2022-05-24 | 123 | 12500  | 1
2022-05-23 | 123 | 12500  | 1
2022-05-16 | 123 | 12500  | 1
2022-05-15 | 123 | 9800   | 2
2022-05-13 | 123 | 9800   | 2
2022-05-12 | 123 | 8400   | 3
2022-05-08 | 123 | 8400   | 3
2022-05-04 | 123 | 15600  | 4
2022-05-02 | 123 | 15600  | 4

Can anyone please assist with the SQL query that may help us generate this column budget_rank.?

What I tried is:

SELECT 
  Date, 
  CID, 
  Budget, 
  DENSE_RANK() OVER (ORDER BY Budget)
FROM table;

But this dint gave us the expected output!

I need to make sure that the Budget_rank column is generated, exactly in the same fashion as shown in the table above. Any help with the query or direction will really help. TIA.

CodePudding user response:

You can't approach this problem with a DENSE_RANK function, as your ranking does not follow a specific order of budgets. What you can instead do is using a variable that assigns a value until a new budget is encountered. You check for new budget using the LAG window function:

SET @ranking = 0;

WITH cte AS (
    SELECT *,
           LAG(Budget) OVER(PARTITION BY CID) AS LastBudget
    FROM tab
)
SELECT Date_,
       CID,
       Budget,
       IF(LastBudget = Budget,
          @ranking, 
          @ranking := @ranking  1
       ) YourRanking
FROM cte

Check this SQL Fiddle.

CodePudding user response:

First use LAG() window function to get the previous Budget of each row and create a boolean flag of 1 or 0 depending on whether the previous Budget is different than the current Budget and then sum over the flags to create the column Budget_rank:

SELECT Date, CID, Budget,
       SUM(flag) OVER (PARTITION BY CID ORDER BY Date DESC) Budget_rank
FROM (
  SELECT *, Budget <> LAG(Budget, 1, -1) OVER (PARTITION BY CID ORDER BY Date DESC) flag
  FROM tablename
) t
ORDER BY Date DESC;

See the demo.

  • Related