SQL Server - Mejor Vendedor por región
-
21-09-2019 - |
Pregunta
SELECT region, person, sum(dollars) as thousands
FROM sales
GROUP BY region, person
ORDER BY region, sum(dollars) desc
El SQL anterior produce una lista completa de personal de ventas por región como esto
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
Si sólo estoy interesado en mostrar el mejor vendedor por región (como abajo), ¿cómo es la mejor forma de hacer eso?
region person thousands
canada mike smith $114
usa john doe $253
europe pieter tsu $546
Solución
He hecho algo así como burnall sugirió. Que no estaba recibiendo mucho amor con la parte "superior 1 con lazos", así que hice todo el asunto una subconsulta y eligió filas donde rango = 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
Tenga en cuenta que esto también funciona para los lazos ya rango () parece poner la misma clasificación en cantidades que son iguales.
Otros consejos
El uso del servidor SQL 2005 + usted puede hacer esto mediante un ROW_NUMBER ()
Tener un vistazo a este ejemplo 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
En SQL Server 2005 y sobre el uso ROW_NUMBER
con PARTITION BY
. Siguiente debe funcionar (no probado, y, probablemente, se puede acortar):
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
En primer lugar no entiendo por qué la cuenta (*) está en $. Mi solución es similar a la existente, pero más corto y creo que más rápido
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
Esto no es demasiado difícil. Esta consulta va a hacer exactamente lo que quiere.
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
Puede utilizar el agregado max (). Es probable que sea menos eficiente que las otras alternativas, ya que va a hacer dos veces por grupo
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
para encontrar la parte superior 5 vendedor por las ventas para cada región
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