[{"data":1,"prerenderedAt":1137},["ShallowReactive",2],{"blog-\u002Fblog\u002Fsql-ranking-functions-row-number-rank":3},{"id":4,"title":5,"body":6,"description":1123,"difficulty":1124,"extension":1125,"framework":1126,"frameworkSlug":57,"meta":1127,"navigation":411,"order":72,"path":1128,"qaPath":1129,"seo":1130,"stem":1131,"subtopic":1132,"topic":1133,"topicSlug":1134,"updated":1135,"__hash__":1136},"blog\u002Fblog\u002Fsql-ranking-functions-row-number-rank.md","SQL Ranking Functions — ROW_NUMBER, RANK, DENSE_RANK, and NTILE",{"type":7,"value":8,"toc":1113},"minimark",[9,14,18,41,45,52,154,160,266,277,281,284,309,425,436,440,705,709,719,834,838,848,950,954,961,1075,1079,1109],[10,11,13],"h2",{"id":12},"why-ranking-functions-matter","Why ranking functions matter",[15,16,17],"p",{},"Ranking functions assign a position number to each row within a window partition.\nThey are the practical solution for three everyday problems:",[19,20,21,29,35],"ul",{},[22,23,24,28],"li",{},[25,26,27],"strong",{},"Top-N per group"," — the best-selling product per category, the latest order\nper customer, the highest-scoring ticket per agent.",[22,30,31,34],{},[25,32,33],{},"Deduplication"," — keeping one row per entity when a table has duplicates.",[22,36,37,40],{},[25,38,39],{},"Bucketing"," — dividing a result set into percentiles or quartiles.",[10,42,44],{"id":43},"row_number-unique-sequential-number","ROW_NUMBER — unique sequential number",[15,46,47,51],{},[48,49,50],"code",{},"ROW_NUMBER()"," gives each row a unique integer starting from 1 within its\npartition. Ties get different numbers (arbitrarily assigned by the database).",[53,54,59],"pre",{"className":55,"code":56,"language":57,"meta":58,"style":58},"language-sql shiki shiki-themes github-light github-dark","-- Assign a row number within each customer's orders (newest first)\nSELECT\n    id,\n    customer_id,\n    total_amount,\n    created_at,\n    ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY created_at DESC) AS rn\nFROM orders;\n","sql","",[48,60,61,70,77,84,90,96,102,145],{"__ignoreMap":58},[62,63,66],"span",{"class":64,"line":65},"line",1,[62,67,69],{"class":68},"sJ8bj","-- Assign a row number within each customer's orders (newest first)\n",[62,71,73],{"class":64,"line":72},2,[62,74,76],{"class":75},"szBVR","SELECT\n",[62,78,80],{"class":64,"line":79},3,[62,81,83],{"class":82},"sVt8B","    id,\n",[62,85,87],{"class":64,"line":86},4,[62,88,89],{"class":82},"    customer_id,\n",[62,91,93],{"class":64,"line":92},5,[62,94,95],{"class":82},"    total_amount,\n",[62,97,99],{"class":64,"line":98},6,[62,100,101],{"class":82},"    created_at,\n",[62,103,105,109,112,115,118,121,124,127,130,133,136,139,142],{"class":64,"line":104},7,[62,106,108],{"class":107},"sj4cs","    ROW_NUMBER",[62,110,111],{"class":82},"() ",[62,113,114],{"class":75},"OVER",[62,116,117],{"class":82}," (",[62,119,120],{"class":75},"PARTITION",[62,122,123],{"class":75}," BY",[62,125,126],{"class":82}," customer_id ",[62,128,129],{"class":75},"ORDER BY",[62,131,132],{"class":82}," created_at ",[62,134,135],{"class":75},"DESC",[62,137,138],{"class":82},") ",[62,140,141],{"class":75},"AS",[62,143,144],{"class":82}," rn\n",[62,146,148,151],{"class":64,"line":147},8,[62,149,150],{"class":75},"FROM",[62,152,153],{"class":82}," orders;\n",[15,155,156,159],{},[25,157,158],{},"Pattern: get the most recent row per group"," (the classic N=1 use case):",[53,161,163],{"className":55,"code":162,"language":57,"meta":58,"style":58},"-- Latest order per customer\nWITH ranked AS (\n    SELECT\n        *,\n        ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY created_at DESC) AS rn\n    FROM orders\n)\nSELECT * FROM ranked WHERE rn = 1;\n",[48,164,165,170,183,188,196,225,233,238],{"__ignoreMap":58},[62,166,167],{"class":64,"line":65},[62,168,169],{"class":68},"-- Latest order per customer\n",[62,171,172,175,178,180],{"class":64,"line":72},[62,173,174],{"class":75},"WITH",[62,176,177],{"class":82}," ranked ",[62,179,141],{"class":75},[62,181,182],{"class":82}," (\n",[62,184,185],{"class":64,"line":79},[62,186,187],{"class":75},"    SELECT\n",[62,189,190,193],{"class":64,"line":86},[62,191,192],{"class":75},"        *",[62,194,195],{"class":82},",\n",[62,197,198,201,203,205,207,209,211,213,215,217,219,221,223],{"class":64,"line":92},[62,199,200],{"class":107},"        ROW_NUMBER",[62,202,111],{"class":82},[62,204,114],{"class":75},[62,206,117],{"class":82},[62,208,120],{"class":75},[62,210,123],{"class":75},[62,212,126],{"class":82},[62,214,129],{"class":75},[62,216,132],{"class":82},[62,218,135],{"class":75},[62,220,138],{"class":82},[62,222,141],{"class":75},[62,224,144],{"class":82},[62,226,227,230],{"class":64,"line":98},[62,228,229],{"class":75},"    FROM",[62,231,232],{"class":82}," orders\n",[62,234,235],{"class":64,"line":104},[62,236,237],{"class":82},")\n",[62,239,240,243,246,249,251,254,257,260,263],{"class":64,"line":147},[62,241,242],{"class":75},"SELECT",[62,244,245],{"class":75}," *",[62,247,248],{"class":75}," FROM",[62,250,177],{"class":82},[62,252,253],{"class":75},"WHERE",[62,255,256],{"class":82}," rn ",[62,258,259],{"class":75},"=",[62,261,262],{"class":107}," 1",[62,264,265],{"class":82},";\n",[15,267,268,269,272,273,276],{},"This works even when ",[48,270,271],{},"MAX(created_at)"," is ambiguous (multiple orders at the same\ntimestamp) — ",[48,274,275],{},"ROW_NUMBER"," always assigns a unique 1 to exactly one row.",[10,278,280],{"id":279},"rank-vs-dense_rank-handling-ties","RANK vs DENSE_RANK — handling ties",[15,282,283],{},"Both assign the same number to tied rows, but differ in what comes next.",[19,285,286,298],{},[22,287,288,293,294,297],{},[25,289,290],{},[48,291,292],{},"RANK()"," — skips position numbers after a tie: 1, 2, 2, ",[25,295,296],{},"4"," (gap)",[22,299,300,305,306],{},[25,301,302],{},[48,303,304],{},"DENSE_RANK()"," — no gaps: 1, 2, 2, ",[25,307,308],{},"3",[53,310,312],{"className":55,"code":311,"language":57,"meta":58,"style":58},"-- Sales leaderboard for the current month\nSELECT\n    employee_id,\n    total_sales,\n    RANK()       OVER (ORDER BY total_sales DESC) AS rank,\n    DENSE_RANK() OVER (ORDER BY total_sales DESC) AS dense_rank\nFROM monthly_sales\nWHERE month = '2026-06-01';\n\n-- rank:        1, 2, 2, 4, 5\n-- dense_rank:  1, 2, 2, 3, 4\n",[48,313,314,319,323,328,333,359,383,390,406,413,419],{"__ignoreMap":58},[62,315,316],{"class":64,"line":65},[62,317,318],{"class":68},"-- Sales leaderboard for the current month\n",[62,320,321],{"class":64,"line":72},[62,322,76],{"class":75},[62,324,325],{"class":64,"line":79},[62,326,327],{"class":82},"    employee_id,\n",[62,329,330],{"class":64,"line":86},[62,331,332],{"class":82},"    total_sales,\n",[62,334,335,338,341,343,345,347,350,352,354,356],{"class":64,"line":92},[62,336,337],{"class":107},"    RANK",[62,339,340],{"class":82},"()       ",[62,342,114],{"class":75},[62,344,117],{"class":82},[62,346,129],{"class":75},[62,348,349],{"class":82}," total_sales ",[62,351,135],{"class":75},[62,353,138],{"class":82},[62,355,141],{"class":75},[62,357,358],{"class":82}," rank,\n",[62,360,361,364,366,368,370,372,374,376,378,380],{"class":64,"line":98},[62,362,363],{"class":107},"    DENSE_RANK",[62,365,111],{"class":82},[62,367,114],{"class":75},[62,369,117],{"class":82},[62,371,129],{"class":75},[62,373,349],{"class":82},[62,375,135],{"class":75},[62,377,138],{"class":82},[62,379,141],{"class":75},[62,381,382],{"class":82}," dense_rank\n",[62,384,385,387],{"class":64,"line":104},[62,386,150],{"class":75},[62,388,389],{"class":82}," monthly_sales\n",[62,391,392,394,397,400,404],{"class":64,"line":147},[62,393,253],{"class":75},[62,395,396],{"class":75}," month",[62,398,399],{"class":75}," =",[62,401,403],{"class":402},"sZZnC"," '2026-06-01'",[62,405,265],{"class":82},[62,407,409],{"class":64,"line":408},9,[62,410,412],{"emptyLinePlaceholder":411},true,"\n",[62,414,416],{"class":64,"line":415},10,[62,417,418],{"class":68},"-- rank:        1, 2, 2, 4, 5\n",[62,420,422],{"class":64,"line":421},11,[62,423,424],{"class":68},"-- dense_rank:  1, 2, 2, 3, 4\n",[15,426,427,428,431,432,435],{},"Use ",[48,429,430],{},"DENSE_RANK"," when \"rank 3\" should mean \"the third distinct performance\nlevel\". Use ",[48,433,434],{},"RANK"," when gaps are acceptable or meaningful (e.g., a sports\nleague where tied teams share a position and the next is truly skipped).",[10,437,439],{"id":438},"top-n-per-group-with-rank","Top-N per group with RANK",[53,441,443],{"className":55,"code":442,"language":57,"meta":58,"style":58},"-- Top 3 products by revenue in each category\nWITH product_revenue AS (\n    SELECT\n        p.id,\n        p.product_name,\n        p.category,\n        SUM(i.unit_price * i.quantity) AS revenue\n    FROM order_items i\n    JOIN products    p ON p.id = i.product_id\n    GROUP BY p.id, p.product_name, p.category\n),\nranked AS (\n    SELECT *,\n           RANK() OVER (PARTITION BY category ORDER BY revenue DESC) AS rnk\n    FROM product_revenue\n)\nSELECT category, product_name, revenue, rnk\nFROM ranked\nWHERE rnk \u003C= 3\nORDER BY category, rnk;\n",[48,444,445,450,461,465,478,489,500,533,540,567,596,601,611,621,654,662,667,675,683,697],{"__ignoreMap":58},[62,446,447],{"class":64,"line":65},[62,448,449],{"class":68},"-- Top 3 products by revenue in each category\n",[62,451,452,454,457,459],{"class":64,"line":72},[62,453,174],{"class":75},[62,455,456],{"class":82}," product_revenue ",[62,458,141],{"class":75},[62,460,182],{"class":82},[62,462,463],{"class":64,"line":79},[62,464,187],{"class":75},[62,466,467,470,473,476],{"class":64,"line":86},[62,468,469],{"class":107},"        p",[62,471,472],{"class":82},".",[62,474,475],{"class":107},"id",[62,477,195],{"class":82},[62,479,480,482,484,487],{"class":64,"line":92},[62,481,469],{"class":107},[62,483,472],{"class":82},[62,485,486],{"class":107},"product_name",[62,488,195],{"class":82},[62,490,491,493,495,498],{"class":64,"line":98},[62,492,469],{"class":107},[62,494,472],{"class":82},[62,496,497],{"class":107},"category",[62,499,195],{"class":82},[62,501,502,505,508,511,513,516,518,521,523,526,528,530],{"class":64,"line":104},[62,503,504],{"class":107},"        SUM",[62,506,507],{"class":82},"(",[62,509,510],{"class":107},"i",[62,512,472],{"class":82},[62,514,515],{"class":107},"unit_price",[62,517,245],{"class":75},[62,519,520],{"class":107}," i",[62,522,472],{"class":82},[62,524,525],{"class":107},"quantity",[62,527,138],{"class":82},[62,529,141],{"class":75},[62,531,532],{"class":82}," revenue\n",[62,534,535,537],{"class":64,"line":147},[62,536,229],{"class":75},[62,538,539],{"class":82}," order_items i\n",[62,541,542,545,548,551,554,556,558,560,562,564],{"class":64,"line":408},[62,543,544],{"class":75},"    JOIN",[62,546,547],{"class":82}," products    p ",[62,549,550],{"class":75},"ON",[62,552,553],{"class":107}," p",[62,555,472],{"class":82},[62,557,475],{"class":107},[62,559,399],{"class":75},[62,561,520],{"class":107},[62,563,472],{"class":82},[62,565,566],{"class":107},"product_id\n",[62,568,569,572,574,576,578,581,583,585,587,589,591,593],{"class":64,"line":415},[62,570,571],{"class":75},"    GROUP BY",[62,573,553],{"class":107},[62,575,472],{"class":82},[62,577,475],{"class":107},[62,579,580],{"class":82},", ",[62,582,15],{"class":107},[62,584,472],{"class":82},[62,586,486],{"class":107},[62,588,580],{"class":82},[62,590,15],{"class":107},[62,592,472],{"class":82},[62,594,595],{"class":107},"category\n",[62,597,598],{"class":64,"line":421},[62,599,600],{"class":82},"),\n",[62,602,604,607,609],{"class":64,"line":603},12,[62,605,606],{"class":82},"ranked ",[62,608,141],{"class":75},[62,610,182],{"class":82},[62,612,614,617,619],{"class":64,"line":613},13,[62,615,616],{"class":75},"    SELECT",[62,618,245],{"class":75},[62,620,195],{"class":82},[62,622,624,627,629,631,633,635,637,640,642,645,647,649,651],{"class":64,"line":623},14,[62,625,626],{"class":107},"           RANK",[62,628,111],{"class":82},[62,630,114],{"class":75},[62,632,117],{"class":82},[62,634,120],{"class":75},[62,636,123],{"class":75},[62,638,639],{"class":82}," category ",[62,641,129],{"class":75},[62,643,644],{"class":82}," revenue ",[62,646,135],{"class":75},[62,648,138],{"class":82},[62,650,141],{"class":75},[62,652,653],{"class":82}," rnk\n",[62,655,657,659],{"class":64,"line":656},15,[62,658,229],{"class":75},[62,660,661],{"class":82}," product_revenue\n",[62,663,665],{"class":64,"line":664},16,[62,666,237],{"class":82},[62,668,670,672],{"class":64,"line":669},17,[62,671,242],{"class":75},[62,673,674],{"class":82}," category, product_name, revenue, rnk\n",[62,676,678,680],{"class":64,"line":677},18,[62,679,150],{"class":75},[62,681,682],{"class":82}," ranked\n",[62,684,686,688,691,694],{"class":64,"line":685},19,[62,687,253],{"class":75},[62,689,690],{"class":82}," rnk ",[62,692,693],{"class":75},"\u003C=",[62,695,696],{"class":107}," 3\n",[62,698,700,702],{"class":64,"line":699},20,[62,701,129],{"class":75},[62,703,704],{"class":82}," category, rnk;\n",[10,706,708],{"id":707},"ntile-dividing-into-buckets","NTILE — dividing into buckets",[15,710,711,714,715,718],{},[48,712,713],{},"NTILE(n)"," divides rows into ",[48,716,717],{},"n"," roughly equal buckets and labels each row with\nits bucket number (1 to n). Useful for quartiles, deciles, and percentile bands.",[53,720,722],{"className":55,"code":721,"language":57,"meta":58,"style":58},"-- Divide customers into 4 revenue quartiles\nWITH customer_revenue AS (\n    SELECT customer_id, SUM(total_amount) AS lifetime_value\n    FROM orders\n    GROUP BY customer_id\n)\nSELECT\n    customer_id,\n    lifetime_value,\n    NTILE(4) OVER (ORDER BY lifetime_value DESC) AS quartile\nFROM customer_revenue;\n-- quartile 1 = top 25% spenders (highest LTV)\n-- quartile 4 = bottom 25% spenders\n",[48,723,724,729,740,758,764,771,775,779,783,788,817,824,829],{"__ignoreMap":58},[62,725,726],{"class":64,"line":65},[62,727,728],{"class":68},"-- Divide customers into 4 revenue quartiles\n",[62,730,731,733,736,738],{"class":64,"line":72},[62,732,174],{"class":75},[62,734,735],{"class":82}," customer_revenue ",[62,737,141],{"class":75},[62,739,182],{"class":82},[62,741,742,744,747,750,753,755],{"class":64,"line":79},[62,743,616],{"class":75},[62,745,746],{"class":82}," customer_id, ",[62,748,749],{"class":107},"SUM",[62,751,752],{"class":82},"(total_amount) ",[62,754,141],{"class":75},[62,756,757],{"class":82}," lifetime_value\n",[62,759,760,762],{"class":64,"line":86},[62,761,229],{"class":75},[62,763,232],{"class":82},[62,765,766,768],{"class":64,"line":92},[62,767,571],{"class":75},[62,769,770],{"class":82}," customer_id\n",[62,772,773],{"class":64,"line":98},[62,774,237],{"class":82},[62,776,777],{"class":64,"line":104},[62,778,76],{"class":75},[62,780,781],{"class":64,"line":147},[62,782,89],{"class":82},[62,784,785],{"class":64,"line":408},[62,786,787],{"class":82},"    lifetime_value,\n",[62,789,790,793,795,797,799,801,803,805,808,810,812,814],{"class":64,"line":415},[62,791,792],{"class":107},"    NTILE",[62,794,507],{"class":82},[62,796,296],{"class":107},[62,798,138],{"class":82},[62,800,114],{"class":75},[62,802,117],{"class":82},[62,804,129],{"class":75},[62,806,807],{"class":82}," lifetime_value ",[62,809,135],{"class":75},[62,811,138],{"class":82},[62,813,141],{"class":75},[62,815,816],{"class":82}," quartile\n",[62,818,819,821],{"class":64,"line":421},[62,820,150],{"class":75},[62,822,823],{"class":82}," customer_revenue;\n",[62,825,826],{"class":64,"line":603},[62,827,828],{"class":68},"-- quartile 1 = top 25% spenders (highest LTV)\n",[62,830,831],{"class":64,"line":613},[62,832,833],{"class":68},"-- quartile 4 = bottom 25% spenders\n",[10,835,837],{"id":836},"percent_rank-and-cume_dist","PERCENT_RANK and CUME_DIST",[15,839,840,843,844,847],{},[48,841,842],{},"PERCENT_RANK()"," returns a value between 0 and 1 representing relative rank.\n",[48,845,846],{},"CUME_DIST()"," returns the fraction of rows with a value ≤ the current row.",[53,849,851],{"className":55,"code":850,"language":57,"meta":58,"style":58},"-- What percentile is each order in, by total amount?\nSELECT\n    id,\n    total_amount,\n    ROUND(PERCENT_RANK() OVER (ORDER BY total_amount) * 100, 1) AS percentile,\n    ROUND(CUME_DIST()    OVER (ORDER BY total_amount) * 100, 1) AS cumulative_pct\nFROM orders;\n",[48,852,853,858,862,866,870,909,944],{"__ignoreMap":58},[62,854,855],{"class":64,"line":65},[62,856,857],{"class":68},"-- What percentile is each order in, by total amount?\n",[62,859,860],{"class":64,"line":72},[62,861,76],{"class":75},[62,863,864],{"class":64,"line":79},[62,865,83],{"class":82},[62,867,868],{"class":64,"line":86},[62,869,95],{"class":82},[62,871,872,875,877,880,882,884,886,888,891,894,897,899,902,904,906],{"class":64,"line":92},[62,873,874],{"class":107},"    ROUND",[62,876,507],{"class":82},[62,878,879],{"class":107},"PERCENT_RANK",[62,881,111],{"class":82},[62,883,114],{"class":75},[62,885,117],{"class":82},[62,887,129],{"class":75},[62,889,890],{"class":82}," total_amount) ",[62,892,893],{"class":75},"*",[62,895,896],{"class":107}," 100",[62,898,580],{"class":82},[62,900,901],{"class":107},"1",[62,903,138],{"class":82},[62,905,141],{"class":75},[62,907,908],{"class":82}," percentile,\n",[62,910,911,913,915,918,921,923,925,927,929,931,933,935,937,939,941],{"class":64,"line":98},[62,912,874],{"class":107},[62,914,507],{"class":82},[62,916,917],{"class":107},"CUME_DIST",[62,919,920],{"class":82},"()    ",[62,922,114],{"class":75},[62,924,117],{"class":82},[62,926,129],{"class":75},[62,928,890],{"class":82},[62,930,893],{"class":75},[62,932,896],{"class":107},[62,934,580],{"class":82},[62,936,901],{"class":107},[62,938,138],{"class":82},[62,940,141],{"class":75},[62,942,943],{"class":82}," cumulative_pct\n",[62,945,946,948],{"class":64,"line":104},[62,947,150],{"class":75},[62,949,153],{"class":82},[10,951,953],{"id":952},"deduplication-with-row_number","Deduplication with ROW_NUMBER",[15,955,956,957,960],{},"Ranking functions are the cleanest way to remove duplicates in a ",[48,958,959],{},"DELETE"," or\nidentify them in a report:",[53,962,964],{"className":55,"code":963,"language":57,"meta":58,"style":58},"-- Find duplicate customer rows (same email, keep the oldest id)\nWITH dupes AS (\n    SELECT id,\n           ROW_NUMBER() OVER (PARTITION BY email ORDER BY id ASC) AS rn\n    FROM customers\n)\nDELETE FROM customers WHERE id IN (\n    SELECT id FROM dupes WHERE rn > 1\n);\n",[48,965,966,971,982,989,1021,1028,1032,1050,1070],{"__ignoreMap":58},[62,967,968],{"class":64,"line":65},[62,969,970],{"class":68},"-- Find duplicate customer rows (same email, keep the oldest id)\n",[62,972,973,975,978,980],{"class":64,"line":72},[62,974,174],{"class":75},[62,976,977],{"class":82}," dupes ",[62,979,141],{"class":75},[62,981,182],{"class":82},[62,983,984,986],{"class":64,"line":79},[62,985,616],{"class":75},[62,987,988],{"class":82}," id,\n",[62,990,991,994,996,998,1000,1002,1004,1007,1009,1012,1015,1017,1019],{"class":64,"line":86},[62,992,993],{"class":107},"           ROW_NUMBER",[62,995,111],{"class":82},[62,997,114],{"class":75},[62,999,117],{"class":82},[62,1001,120],{"class":75},[62,1003,123],{"class":75},[62,1005,1006],{"class":82}," email ",[62,1008,129],{"class":75},[62,1010,1011],{"class":82}," id ",[62,1013,1014],{"class":75},"ASC",[62,1016,138],{"class":82},[62,1018,141],{"class":75},[62,1020,144],{"class":82},[62,1022,1023,1025],{"class":64,"line":92},[62,1024,229],{"class":75},[62,1026,1027],{"class":82}," customers\n",[62,1029,1030],{"class":64,"line":98},[62,1031,237],{"class":82},[62,1033,1034,1036,1038,1041,1043,1045,1048],{"class":64,"line":104},[62,1035,959],{"class":75},[62,1037,248],{"class":75},[62,1039,1040],{"class":82}," customers ",[62,1042,253],{"class":75},[62,1044,1011],{"class":82},[62,1046,1047],{"class":75},"IN",[62,1049,182],{"class":82},[62,1051,1052,1054,1056,1058,1060,1062,1064,1067],{"class":64,"line":147},[62,1053,616],{"class":75},[62,1055,1011],{"class":82},[62,1057,150],{"class":75},[62,1059,977],{"class":82},[62,1061,253],{"class":75},[62,1063,256],{"class":82},[62,1065,1066],{"class":75},">",[62,1068,1069],{"class":107}," 1\n",[62,1071,1072],{"class":64,"line":408},[62,1073,1074],{"class":82},");\n",[10,1076,1078],{"id":1077},"recap","Recap",[15,1080,1081,1083,1084,1086,1087,1089,1090,1092,1093,1095,1096,1098,1099,1101,1102,1104,1105,1108],{},[48,1082,275],{}," gives every row a unique number — ideal for top-1-per-group and\ndeduplication. ",[48,1085,434],{}," and ",[48,1088,430],{}," handle ties: ",[48,1091,434],{}," leaves gaps,\n",[48,1094,430],{}," does not. ",[48,1097,713],{}," buckets rows into n equal groups. All four\nrequire an ",[48,1100,129],{}," in the ",[48,1103,114],{}," clause to be meaningful. For top-N per\ngroup, wrap the ranking in a CTE and filter ",[48,1106,1107],{},"WHERE rn \u003C= N"," in the outer query.",[1110,1111,1112],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":58,"searchDepth":72,"depth":72,"links":1114},[1115,1116,1117,1118,1119,1120,1121,1122],{"id":12,"depth":72,"text":13},{"id":43,"depth":72,"text":44},{"id":279,"depth":72,"text":280},{"id":438,"depth":72,"text":439},{"id":707,"depth":72,"text":708},{"id":836,"depth":72,"text":837},{"id":952,"depth":72,"text":953},{"id":1077,"depth":72,"text":1078},"SQL ROW_NUMBER, RANK, DENSE_RANK, NTILE, and PERCENT_RANK — differences explained with real examples for top-N filtering, deduplication, and bucketing.","medium","md","SQL",{},"\u002Fblog\u002Fsql-ranking-functions-row-number-rank","\u002Fsql\u002Fwindow-functions\u002Franking-functions",{"title":5,"description":1123},"blog\u002Fsql-ranking-functions-row-number-rank","Ranking Functions","Window Functions","window-functions","2026-06-20","wFEQFzTlFeH3Q1YBJ3zVK_0u5I_J82NkHhmf8J4uyOA",1782244088594]