Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DENSE_RANK according to particular order

Hi I have a table of data I want to output the dense_rank of the names starting from the first group of names according to sorted dates order. e.g.

DROP TABLE MyTable
SELECT * INTO MyTable FROM (
  VALUES ('2015-12-23', 'ccc'),('2015-12-21', 'aaa'),
         ('2015-12-20', 'bbb'),('2015-12-22', 'aaa')
) t (date, name)
SELECT DENSE_RANK() OVER (ORDER BY name) rank, * FROM MyTable ORDER BY date

For the query above I got

rank    date    name
2   2015-12-20  bbb
1   2015-12-21  aaa
1   2015-12-22  aaa
3   2015-12-23  ccc

You can see the dates are sorted (good), ranks are assigned to names in group (good), but the ranks do not start from the first group of name, e.g. I want

rank    date    name
1   2015-12-20  bbb
2   2015-12-21  aaa
2   2015-12-22  aaa
3   2015-12-23  ccc

How would you correct the query? If there are multiple working answers, the simplest/shortest one will be picked as the answer. Thanks.

Added:

Thanks @lad2025 and @GiorgosBetsos for clarifying my question. Sorting is straightly according to dates and dates are unique in my case. Names can repeat and appear non-consecutively. So with ('2015-12-24', 'aaa'), the output is

rank    date    name
1   2015-12-20  bbb
2   2015-12-21  aaa
2   2015-12-22  aaa
3   2015-12-23  ccc
4   2015-12-24  aaa
like image 421
user1589188 Avatar asked Dec 23 '15 06:12

user1589188


People also ask

What is DENSE_RANK () in SQL?

DENSE_RANK computes the rank of a row in an ordered group of rows and returns the rank as a NUMBER . The ranks are consecutive integers beginning with 1. The largest rank value is the number of unique values returned by the query.

What is the difference between RANK () and DENSE_RANK () explain using an example?

rank and dense_rank are similar to row_number , but when there are ties, they will give the same value to the tied values. rank will keep the ranking, so the numbering may go 1, 2, 2, 4 etc, whereas dense_rank will never give any gaps.

Which one is correct use of DENSE_RANK function?

The Oracle/PLSQL DENSE_RANK function returns the rank of a row in a group of rows. It is very similar to the RANK function. However, the RANK function can cause non-consecutive rankings if the tested values are the same. Whereas, the DENSE_RANK function will always result in consecutive rankings.

How do I create a dense RANK in SQL?

The syntax of the DENSE_RANK() function is as follows: DENSE_RANK() OVER ( [PARTITION BY partition_expression, ... ] ORDER BY sort_expression [ASC | DESC], ... ) The DENSE_RANK( ) function is applied to the rows of each partition defined by the PARTITION BY clause, in a specified order, defined by ORDER BY clause.


2 Answers

You can use:

SELECT DENSE_RANK() OVER (ORDER BY minGrpDate),
       [date], name
FROM (
  SELECT MIN([date]) OVER (PARTITION BY grp) AS minGrpDate,
         [date], name
  FROM (       
    SELECT [date], name,
           ROW_NUMBER() OVER (ORDER BY [date])
           -
           ROW_NUMBER() OVER (PARTITION BY name ORDER BY [date]) AS grp
    FROM mytable) AS t ) AS s
ORDER BY Date

Explanation:

  • grp field identifies islands of consecutive records having the same name.
  • minGrpDate, which is calculated using grp, is the minimum date of each island.
  • Using minGrpDate we can now apply DENSE_RANK() to get required rank.

Note1: The above query handles discontinuities in name field, i.e. the case of non-consecutive fields having the same name.

Note2: The query does not handle the case of different name values sharing the same date value.

Demo here

like image 60
Giorgos Betsos Avatar answered Oct 07 '22 16:10

Giorgos Betsos


First rank distinct names ordered by date and then join on the table:

;WITH cte AS(SELECT name, ROW_NUMBER() OVER(ORDER BY MIN(date)) rn 
             FROM dbo.MyTable 
             GROUP BY name)
SELECT c.rn, m.date, m.name
FROM cte c
JOIN dbo.MyTable m ON m.name = c.name
ORDER BY m.date
like image 23
Giorgi Nakeuri Avatar answered Oct 07 '22 18:10

Giorgi Nakeuri