Choosing the Right Ranking Function: Why Ties in SQL Matter

Senior Data Engineer • Contractor / Freelancer • GCP & AWS Certified
Search for a command to run...

Senior Data Engineer • Contractor / Freelancer • GCP & AWS Certified
No comments yet. Be the first to comment.
A focused guide to window functions in BigQuery — cumulative sums, rolling averages, ranking functions, named windows, RANGE frames, and more.
Here’s a quick BigQuery SQL exercise. I often work with cumulative aggregations, but it’s not every day that I need to reverse them—converting cumulative values back into monthly figures. Let's look at an example. The dataset provides cumulative sale...
Here's a useful Dataform concept: pre_operations and post_operations. As the name implies, these represent a set of actions that run before and after the main operation (table, view, or SQL operations

BigQuery has always been a SQL engine for tabular data. Object tables add an interesting twist to that. Instead of rows containing values, an object table gives you one row per file — pointing at da

Query your data lake with warehouse-grade security and performance — without moving a single file.

Ever run a heavy BigQuery SQL query, processed gigabytes of data — and then accidentally closed the tab or forgot to save the results? 😬 Don't re-run it. Your results are still there. BigQuery automa

You can use query parameters in BigQuery hashtag#SQL (now in the console as well!) — but how are they different from variables, and when should you use each? Both parameters and variables act as place

If you’re like me, you probably use QUALIFY + ROW_NUMBER() almost daily for deduplication or finding the first/last occurrence of something. It’s a powerful combo in modern SQL !
But here’s the catch: there are subtle nuances and edge cases that can cause some trouble.
The choice between ordering functions like ROW_NUMBER(), DENSE_RANK(), and RANK() isn’t always straightforward—it depends on the nature of your data and the question you’re trying to answer.
Check out my previous post a quick overview of ordering functions.
Now, let me share a scenario.

We want to find the first event type for each user. Simple enough, right?
But in this case we can have two events happening at the exact same time.
Here’s where things get interesting:
➡️ ROW_NUMBER() would arbitrarily pick one event and mask the tie (non-deterministic behavior).
➡️ DENSE_RANK(), on the other hand, would preserve the tie, allowing us to decide how to handle it.
This subtle difference can have a huge impact on your results!
TL;DR: Keep ties in mind when deciding which numbering function to use.
As always, it’s about using the right tool for the right job.
Have you encountered any tricky scenarios with ties?
Found it useful? Subscribe to my Analytics newsletter at notjustsql.com.
Enjoyed this? Here are some related articles you might find useful: