SQL Ranks
SQL
Download (.zip)
use pubs SET NOCOUNT ON go
-- Approach 1. Standard SQL approach using view. -- Is expensive to run. if (isnull(object_id('ranked_sales'),0)) > 0 DROP VIEW ranked_sales go
CREATE VIEW ranked_sales (rank, title_id, ytd_sales, title) AS SELECT (SELECT COUNT(DISTINCT T2.ytd_sales) FROM titles AS T2 WHERE T2.ytd_sales >= T1.ytd_sales ) AS rank, title_id, ytd_sales, title FROM titles AS T1 WHERE ytd_sales IS NOT NULL GO
SELECT * FROM ranked_sales WHERE rank <= 10 ORDER BY rank GO
-- Approach 2. Without the view. nest a select in select list, and correlate back. -- Also expensive to run. SELECT rank, title_id, ytd_sales, title FROM (SELECT T1.title_id, ytd_sales, T1.title, (SELECT COUNT(DISTINCT T2.ytd_sales) FROM titles AS T2 WHERE T1.ytd_sales <= T2.ytd_sales) AS rank FROM titles AS T1) AS X WHERE ytd_sales IS NOT NULL ORDER BY rank GO
-- Approach 3. Create a temp table with an identity, then do an ordered select to populate it. CREATE TABLE #ranked_order ( rank int IDENTITY NOT NULL PRIMARY KEY , title_id char(6) NOT NULL, ytd_sales int NOT NULL, title varchar(80) NOT NULL ) GO
INSERT #ranked_order SELECT title_id, ytd_sales, title FROM titles WHERE ytd_sales IS NOT NULL ORDER BY ytd_sales DESC
SELECT * FROM #ranked_order
DROP TABLE #ranked_order GO
-- Approach 4A. Create a temp table with an identity, then do an -- ordered select to populate it. -- DO a nested select correlated back to itself to find the lowest -- rank for a given value. CREATE TABLE #ranked_order ( rank int IDENTITY NOT NULL , title_id char(6) NOT NULL, ytd_sales int NOT NULL, title varchar(80) NOT NULL ) GO
INSERT #ranked_order SELECT title_id, ytd_sales, title FROM titles WHERE ytd_sales IS NOT NULL ORDER BY ytd_sales DESC
SELECT B.rank, A.title_id, B.ytd_sales , A.title FROM (SELECT MIN(T2.rank) AS rank, T2.ytd_sales FROM #ranked_order AS T2 GROUP BY T2.ytd_sales) AS B, #ranked_order AS A WHERE A.ytd_sales=B.ytd_sales ORDER BY B.rank
DROP TABLE #ranked_order GO
-- Approach 4B. Same as above, explicitly noting the ties. CREATE TABLE #ranked_order ( rank int IDENTITY NOT NULL , title_id char(6) NOT NULL, ytd_sales int NOT NULL, title varchar(80) NOT NULL ) GO
INSERT #ranked_order SELECT title_id, ytd_sales, title FROM titles WHERE ytd_sales IS NOT NULL ORDER BY ytd_sales DESC
SELECT B.rank, CASE B.number_tied WHEN 1 THEN ' ' ELSE '('+ CONVERT(varchar, number_tied) + ' Way Tie)' END AS tie, A.title_id, B.ytd_sales, A.title FROM (SELECT MIN(T2.rank) AS rank, COUNT(*) AS number_tied, T2.ytd_sales FROM #ranked_order AS T2 GROUP BY T2.ytd_sales) AS B, #ranked_order AS A WHERE A.ytd_sales=B.ytd_sales ORDER BY B.rank
DROP TABLE #ranked_order GO
|