Reputation: 31
I am trying to write a query that will return the top 5 sales in each State that provides the Debtor Name and the Net Total. I have come up with the following which does do the job, however, I'm sure there is a better way, especially if a new State was added.
I have tried to understand the WHERE IN syntax but not I'm not getting it. I'd appreciate any assistance.
SELECT TOP 5 data.DebtorNameShort, data.State, data.NetTotal
FROM data
WHERE State= "VI"
ORDER BY NetTotal DESC
UNION ALL
SELECT TOP 5 data.DebtorNameShort, data.State, data.NetTotal
FROM data
WHERE State= "NS"
ORDER BY NetTotal DESC
UNION ALL
SELECT TOP 5 data.DebtorNameShort, data.State, data.NetTotal
FROM data
WHERE State= "sa"
ORDER BY NetTotal DESC
UNION ALL
SELECT TOP 5 data.DebtorNameShort, data.State, data.NetTotal
FROM data
WHERE State= "wa"
ORDER BY NetTotal DESC
UNION ALL
SELECT TOP 5 data.DebtorNameShort, data.State, data.NetTotal
FROM data
WHERE State= "ta"
ORDER BY NetTotal DESC
UNION ALL
SELECT TOP 5 data.DebtorNameShort, data.State, data.NetTotal
FROM data
WHERE State= "ac"
ORDER BY NetTotal DESC
UNION ALL
SELECT TOP 5 data.DebtorNameShort, data.State, data.NetTotal
FROM data
WHERE State= "ql"
ORDER BY NetTotal DESC
UNION ALL SELECT TOP 5 data.DebtorNameShort, data.State, data.NetTotal
FROM data
WHERE State= "nt"
ORDER BY NetTotal DESC;
Upvotes: 3
Views: 2170
Reputation: 180987
Something like this should work;
WITH cte AS (
SELECT DebtorNameShort, State, NetTotal,
ROW_NUMBER() OVER (PARTITION BY State ORDER BY NetTotal DESC) rn
FROM data
)
SELECT DebtorNameShort, State, NetTotal
FROM cte
WHERE rn <= 5;
Here I'm using a common table expression to get the row number of each row ordered by NetTotal descending, per state. That row number can then easily be used in a query to filter out the top 5 rows per state.
Upvotes: 2
Reputation: 247810
Based on the TOP
syntax I am guessing you are using SQL Server. You should be able to use row_number()
to return the top 5 values for each state:
select DebtorNameShort, State, NetTotal
from
(
select DebtorNameShort, State, NetTotal,
row_number() over(partition by state order by NetTotal desc) seq
from data
) d
where seq <= 5
row_number()
is a windowing function that will allow to to create a sequential value for each item in a partition - for your example you will partition the data by the state
. As long as you order the NetTotal
in descending order then you can filter the final result to only return those rows will a row number of 1-5.
Upvotes: 7