SQL Server - Top Salesperson per Regione
-
21-09-2019 - |
Domanda
SELECT region, person, sum(dollars) as thousands
FROM sales
GROUP BY region, person
ORDER BY region, sum(dollars) desc
Lo SQL sopra produce un elenco completo delle persone di vendite per regione come questo
region person thousands
canada mike smith $114
canada joe blog $76
canada pete dodd $45
usa john doe $253
usa jane smyth $120
europe pieter tsu $546
europ mike lee $520
Se sono interessati solo a mostrare il venditore superiore per regione (come sotto), come posso meglio farlo?
region person thousands
canada mike smith $114
usa john doe $253
europe pieter tsu $546
Soluzione
Ho fatto qualcosa di simile burnall suggerito. Non è stato sempre molto amore con la parte "superiore 1 con i legami", così ho fatto il tutto una sottoquery e scelto le righe in cui ranking = 1.
select *
from
(
select region,
person,
rank() over(partition by region order by sum(dollars) desc) as ranking
from sales
group by region,
person
) temp
where ranking = 1
Si noti che questo funziona anche per i legami dal rango () sembra porre la stessa graduatoria sulle somme che sono uguali.
Altri suggerimenti
utilizza SQL Server 2005 + si potrebbe fare questo usando un ROW_NUMBER ()
Date un'occhiata a questo esempio completo.
DECLARE @sales TABLE(
region VARCHAR(50),
person VARCHAR(50),
Sales FLOAT
)
INSERT INTO @sales SELECT 'canada','mike smith',1
INSERT INTO @sales SELECT 'canada','mike smith',1
INSERT INTO @sales SELECT 'canada','mike smith',1
INSERT INTO @sales SELECT 'canada','mike smith',1
INSERT INTO @sales SELECT 'canada','joe blog',1
INSERT INTO @sales SELECT 'canada','joe blog',1
INSERT INTO @sales SELECT 'canada','pete dodd',1
INSERT INTO @sales SELECT 'usa','john doe',1
INSERT INTO @sales SELECT 'usa','john doe',1
INSERT INTO @sales SELECT 'usa','jane smyth',1
INSERT INTO @sales SELECT 'europe','pieter tsu',1
INSERT INTO @sales SELECT 'europe','pieter tsu',1
INSERT INTO @sales SELECT 'europe','mike lee',1
;WITH Counts AS(
SELECT region,
person,
count(*) as thousands
FROM @sales
GROUP BY region,
person
), CountVals AS(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY region ORDER BY thousands DESC) ROWID
FROM Counts
)
SELECT *
FROM CountVals
WHERE ROWID = 1
In SQL Server 2005 e soprattutto l'uso ROW_NUMBER
con PARTITION BY
. In seguito dovrebbe funzionare (non testato, e probabilmente può essere abbreviato):
WITH total_sales
AS (SELECT region, person, count(*) as thousands
FROM sales
GROUP BY region, person
ORDER BY region, count(*) desc
)
, ranked_sales
AS (SELECT region, person, thousands,
ROW_NUMBER() OVER (PARTITION BY region ORDER BY thousands DESC, person) AS region_rank
FROM total_sales
)
SELECT region, person, thousands
FROM ranked_sales
WHERE region_rank = 1
Prima di tutto io non capisco perché count (*) è in $. La mia soluzione è simile a quello già esistente, ma più breve e credo più veloce
select top 1 with ties region, person, rank() over(partition by region order by count(*) desc)
from sales
group by region, person
order by 3
Questo non è troppo difficile. Questa query farà esattamente quello che vuoi.
select distinct region,
(select top 1 person
from Sales s2 where s2.region = s1.region
group by person
order by SUM(dollars) desc) as person,
(select top 1 SUM(dollars)
from Sales s2 where s2.region = s1.region
group by person
order by SUM(dollars) desc) as thousands
from sales s1
È possibile utilizzare l'aggregato massimo (). E 'probabilmente meno efficiente rispetto alle altre alternative, perché vi ritroverete a fare gruppo per due volte
SELECT region,person,max(thousands) FROM
(SELECT region, person, count(*) as thousands
FROM sales
GROUP BY region, person) tmp
GROUP BY region, person
ORDER BY region, max(thousands) desc
per trovare top 5 commesso dalle vendite per ogni regione
select *
from
(
select region,
[Customer Name],
rank() over(partition by region order by sum(sales) desc) as ranking
from Orders
group by region, [Customer Name]
) temp
where ranking between 1 and 5