SQL Server - Top Salesperson par région
-
21-09-2019 - |
Question
SELECT region, person, sum(dollars) as thousands
FROM sales
GROUP BY region, person
ORDER BY region, sum(dollars) desc
Le SQL produit ci-dessus une liste complète des personnes de ventes par région comme celui-ci
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 je suis seulement intéressé à montrer le meilleur vendeur par région (comme ci-dessous), comment puis-je faire mieux?
region person thousands
canada mike smith $114
usa john doe $253
europe pieter tsu $546
La solution
Je l'ai fait quelque chose comme burnall suggéré. Je ne recevais pas beaucoup d'amour de la partie, donc je fait la chose « top 1 avec des liens » et une sous-requête choisi les lignes où rang = 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
Notez que cela fonctionne aussi pour des liens depuis rang () semble placer le même rang sur les sommes qui sont égales.
Autres conseils
Utilisation Sql Server 2005+ vous pouvez le faire en utilisant un ROW_NUMBER ()
Jetez un oeil à cet exemple complet.
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
Dans SQL Server 2005 et l'utilisation ci-dessus ROW_NUMBER
avec PARTITION BY
. Devrait fonctionner (non testé, et peut probablement être raccourci):
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
D'abord tout ce que je ne comprends pas pourquoi le nombre (*) est en $. Ma solution est similaire à existante, mais plus court et je crois plus rapide
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
Ce n'est pas trop difficile. Cette requête va faire exactement ce que vous voulez.
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
Vous pouvez utiliser l'agrégat max (). Il est probablement moins efficace que les autres alternatives parce que vous allez faire deux fois par groupe
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
pour trouver top 5 vendeur par les ventes pour chaque région
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