RANK / DENSE_RANK / NTILE
Feb 23, 2026
·
5
min read
Category: Window/Analytic Functions
Platform Support:
✅ Snowflake | ✅ BigQuery | ✅ Databricks
Description
Ranking functions assign ranks to rows within a partition. RANK assigns ranks with gaps after ties, DENSE_RANK assigns ranks without gaps, and NTILE distributes rows into a specified number of groups. Essential for top-N queries, percentile analysis, and data segmentation.
Syntax
Platform-Specific Notes
All Platforms:
Identical syntax and behavior
All are standard SQL window functions
Require ORDER BY clause
Work with PARTITION BY for group-wise ranking
Ranking Functions Comparison
Sample Data:
employee | sales |
|---|---|
Alice | 100 |
Bob | 95 |
Carol | 95 |
David | 90 |
Emma | 85 |
Comparison Results:
employee | sales | ROW_NUMBER | RANK | DENSE_RANK |
|---|---|---|---|---|
Alice | 100 | 1 | 1 | 1 |
Bob | 95 | 2 | 2 | 2 |
Carol | 95 | 3 | 2 | 2 |
David | 90 | 4 | 4 | 3 |
Emma | 85 | 5 | 5 | 4 |
Key Differences:
ROW_NUMBER: Always unique (1,2,3,4,5)
RANK: Skips ranks after ties (1,2,2,4,5)
DENSE_RANK: No gaps in ranks (1,2,2,3,4)
Example 1: RANK - Top Salespeople by Region
All Platforms:
Sample Data (sales_data table):
region | employee_name | sales_amount |
|---|---|---|
East | Alice | 150000 |
East | Bob | 120000 |
East | Carol | 120000 |
East | David | 95000 |
West | Emma | 180000 |
West | Frank | 165000 |
West | Grace | 140000 |
Result:
region | employee_name | sales_amount | sales_rank | dense_sales_rank |
|---|---|---|---|---|
East | Alice | 150000 | 1 | 1 |
East | Bob | 120000 | 2 | 2 |
East | Carol | 120000 | 2 | 2 |
East | David | 95000 | 4 | 3 |
West | Emma | 180000 | 1 | 1 |
West | Frank | 165000 | 2 | 2 |
West | Grace | 140000 | 3 | 3 |
Example 2: Top 3 Products per Category with QUALIFY
Snowflake/BigQuery:
Databricks:
Sample Data (product_sales table):
category | product_name | revenue |
|---|---|---|
Electronics | Laptop | 50000 |
Electronics | Mouse | 8000 |
Electronics | Keyboard | 12000 |
Electronics | Monitor | 30000 |
Furniture | Desk | 25000 |
Furniture | Chair | 18000 |
Furniture | Shelf | 8000 |
Result:
category | product_name | revenue | revenue_rank |
|---|---|---|---|
Electronics | Laptop | 50000 | 1 |
Electronics | Monitor | 30000 | 2 |
Electronics | Keyboard | 12000 | 3 |
Furniture | Desk | 25000 | 1 |
Furniture | Chair | 18000 | 2 |
Furniture | Shelf | 8000 | 3 |
Example 3: NTILE - Quartile Analysis
All Platforms:
Sample Data (customers table):
customer_id | customer_name | lifetime_value |
|---|---|---|
1 | Alice | 5000 |
2 | Bob | 4500 |
3 | Carol | 4000 |
4 | David | 3500 |
5 | Emma | 3000 |
6 | Frank | 2500 |
7 | Grace | 2000 |
8 | Henry | 1500 |
Result:
customer_id | customer_name | lifetime_value | quartile | customer_segment |
|---|---|---|---|---|
1 | Alice | 5000 | 1 | Top 25% (VIP) |
2 | Bob | 4500 | 1 | Top 25% (VIP) |
3 | Carol | 4000 | 2 | Upper 25% |
4 | David | 3500 | 2 | Upper 25% |
5 | Emma | 3000 | 3 | Lower 25% |
6 | Frank | 2500 | 3 | Lower 25% |
7 | Grace | 2000 | 4 | Bottom 25% |
8 | Henry | 1500 | 4 | Bottom 25% |
Example 4: Multiple Rankings with Different Criteria
All Platforms:
Sample Data (employee_performance table):
employee_id | employee_name | sales_amount | customer_satisfaction |
|---|---|---|---|
1 | Alice | 150000 | 4.8 |
2 | Bob | 120000 | 4.9 |
3 | Carol | 180000 | 4.5 |
4 | David | 95000 | 4.7 |
Result:
employee_id | employee_name | sales_amount | customer_satisfaction | sales_rank | satisfaction_rank | combined_rank | sales_decile |
|---|---|---|---|---|---|---|---|
3 | Carol | 180000 | 4.5 | 1 | 4 | 1 | 1 |
1 | Alice | 150000 | 4.8 | 2 | 2 | 2 | 1 |
2 | Bob | 120000 | 4.9 | 3 | 1 | 3 | 2 |
4 | David | 95000 | 4.7 | 4 | 3 | 4 | 2 |
Example 5: Percentile-Based Segmentation
All Platforms:
Result:
segment | customer_count | avg_revenue | min_revenue | max_revenue |
|---|---|---|---|---|
Top 10% | 100 | 15250.00 | 10000.00 | 25000.00 |
Top 25% | 150 | 7200.00 | 5000.00 | 9999.00 |
Top 50% | 250 | 3500.00 | 2000.00 | 4999.00 |
Bottom 50% | 500 | 850.00 | 100.00 | 1999.00 |
Example 6: Year-over-Year Ranking Comparison
All Platforms:
Sample Result:
product_id | product_name | year | annual_sales | yearly_rank | previous_year_rank | rank_change |
|---|---|---|---|---|---|---|
1 | Laptop | 2024 | 500000 | 1 | 3 | -2 |
3 | Monitor | 2024 | 450000 | 2 | 1 | 1 |
2 | Keyboard | 2024 | 400000 | 3 | 2 | 1 |
When to Use Each Function
Function | Use When | Example |
|---|---|---|
RANK | Need standard competition ranking | Olympics medals (ties share rank, next rank skipped) |
DENSE_RANK | Need continuous ranking | Grade levels (A, B, C with no gaps) |
ROW_NUMBER | Need unique row numbers | Pagination, deduplication |
NTILE | Need equal-sized groups | Quartiles, deciles, percentiles |
Common Use Cases
Top N analysis: Best sellers, top performers
Leaderboards: Gaming scores, sales rankings
Customer segmentation: VIP, premium, standard tiers
Performance reviews: Employee rankings
ABC analysis: Inventory categorization
Percentile analysis: Test scores, benchmarking
Performance Tips
Use appropriate function: RANK faster than DENSE_RANK for large datasets
Limit partitions: Fewer partitions = better performance
Index ORDER BY columns: Improves sorting performance
Use QUALIFY: More efficient than subquery in Snowflake/BigQuery
Filter early: Apply WHERE before window functions
Best Practices
Choose right function: Understand tie-handling needs
Define clear ORDER BY: Ensure deterministic rankings
Use PARTITION BY wisely: Group rankings appropriately
Handle ties explicitly: Document how ties are handled
Combine with filters: Use QUALIFY or WHERE for top-N
Test edge cases: Verify behavior with ties and NULLs





