Skip to Main Content
  • Questions
  • How to aribitrarily assign a rank in the event of a tie

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Eric.

Asked: December 05, 2005 - 2:34 am UTC

Last updated: December 05, 2005 - 6:45 am UTC

Version: 9.2.1

Viewed 1000+ times

You Asked

Hello Tom,

I was looking for a solution to use with the rank (or dense_rank) function. I need to have every row receive a distinct rank dispite frequent ties in the data. I would like to arbitrarily assign a rank in the event of a tie, using either the order of occurance or revert to alphabetical in terms of the key.

For example, suppose i have the following table:

CREATE TABLE sales_by_employee (name VARCHAR2(10), sales NUMBER);

that contains the following data:

INSERT INTO sales_by_employee VALUES ('dave', 500);
INSERT INTO sales_by_employee VALUES ('walter', 400);
INSERT INTO sales_by_employee VALUES ('jack', 400);
INSERT INTO sales_by_employee VALUES ('sue', 300);

I would like to produce a report that looks like this:

NAME SALES RANK
dave 500 1
walter 400 2 <-- tie is resolved
jack 400 3 <-- tie is resolved
sue 300 4

Note that the tie was resolved in favor of 'walter' simply because his record was first (I also wouldn't care if it put 'jack' first due to alphabetical precidence).

I searched your site and that the following were the most helpful, but did not ever fully answer this:

</code> http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:2920665938600 http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:12759079666984 <code>

Further, in the documentation there was something about a "TIEBREAKERS" clause, but couldn't find any examples. (i think its for use with OLAP).

Any suggestions?

and Tom said...

just use row_number() instead


ops$tkyte@ORA10G> select a.*, row_number() over (order by sales desc) rnk
2 from sales_by_employee a;

NAME SALES RNK
------------------------------ ---------- ----------
dave 500 1
walter 400 2
jack 400 3
sue 300 4


Rating

  (2 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

looks easier than tennis

A reader, December 05, 2005 - 6:52 am UTC

:-)

Ofir Manor, December 05, 2005 - 12:55 pm UTC

Just a minor thing to add:
ROW_NUMBER is the ultimate tie-breaker function. Use it if you don't care how ties will be handled. However, remember that this tie-breaking is "random" and the order might be non-repeatable.
It is sometimes better to control the tie-breaking rule by adding more columns to the RANK/DENSE_RANK order by:
SELECT a.*, rank() over (order by sales desc,NAME) rnk
FROM sales_by_employee a
If your order by contains a unique key (like the PK of the table), there will be no ties at all. Come to think of it, in this case RANK,DENSE_RANK,ROW_NUMBER will return exactly the same output.



More to Explore

Analytics

Analytic SQL got you confused? Check out Connor McDonald's complete video course.