基于Northwind数据库:如何获取各地区销量最高的产品信息
解决Northwind数据库各地区销量最高产品的查询问题
嘿,这个问题我之前碰到好多次啦——在Northwind数据库里找各地区销量最高的产品,很容易在GROUP BY这里踩坑,咱们来一步步解决它!
先理清你的问题根源
你之前的问题在于:当你把ProductID和ProductName加入SELECT和GROUP BY后,分组粒度从「地区」变成了「地区+产品」,这时候你计算的MaxSoldQuantity其实是每个产品自己的销量(因为每个分组里只有一个产品),所以结果自然和你第一次统计各地区各产品销量的结果完全一致。要拿到各地区的销冠产品,得先统计好每个地区每个产品的销量,再从中筛选出每个地区里销量最高的那些。
方法一:用窗口函数(最直观,支持并列排名)
窗口函数是这类「分组取topN」问题的最优解,推荐用RANK()或者ROW_NUMBER()来实现:
-- 第一步:先统计每个地区每个产品的销售次数(SoldQuantity) WITH RegionProductSales AS ( SELECT c.Region, p.ProductID, p.ProductName, COUNT(od.OrderID) AS SoldQuantity -- 如果是统计销售数量,改成SUM(od.Quantity)即可 FROM Customers c JOIN Orders o ON c.CustomerID = o.CustomerID JOIN [Order Details] od ON o.OrderID = od.OrderID JOIN Products p ON od.ProductID = p.ProductID -- 可选:过滤空地区 WHERE c.Region IS NOT NULL AND c.Region != '' GROUP BY c.Region, p.ProductID, p.ProductName ), -- 第二步:给每个地区的产品按销量降序排名 RankedProducts AS ( SELECT *, -- 用RANK()会保留并列第一的产品;用ROW_NUMBER()则只取一个(按ProductID排序) RANK() OVER (PARTITION BY Region ORDER BY SoldQuantity DESC) AS SalesRank FROM RegionProductSales ) -- 第三步:筛选出每个地区排名第一的产品 SELECT Region, ProductID, ProductName, SoldQuantity FROM RankedProducts WHERE SalesRank = 1;
小提示:
- 如果你的「SoldQuantity」是指销售数量(而非订单次数),把
COUNT(od.OrderID)改成SUM(od.Quantity)即可。 RANK()和ROW_NUMBER()的区别:如果一个地区有多个产品销量并列最高,RANK()会把它们都标记为第1名并返回;ROW_NUMBER()则会按ProductID顺序给它们分配不同排名,只返回其中一个。
方法二:用子查询关联(适合不支持窗口函数的旧版SQL)
如果你的SQL环境不支持窗口函数(比如非常老的SQL Server版本),可以用「先统计各地区最高销量,再关联回销量表」的方式:
WITH RegionProductSales AS ( SELECT c.Region, p.ProductID, p.ProductName, COUNT(od.OrderID) AS SoldQuantity FROM Customers c JOIN Orders o ON c.CustomerID = o.CustomerID JOIN [Order Details] od ON o.OrderID = od.OrderID JOIN Products p ON od.ProductID = p.ProductID WHERE c.Region IS NOT NULL AND c.Region != '' GROUP BY c.Region, p.ProductID, p.ProductName ), -- 先算出每个地区的最高销量值 RegionMaxSales AS ( SELECT Region, MAX(SoldQuantity) AS MaxSoldQuantity FROM RegionProductSales GROUP BY Region ) -- 关联两个表,筛选出销量等于地区最高值的产品 SELECT rps.Region, rps.ProductID, rps.ProductName, rps.SoldQuantity FROM RegionProductSales rps JOIN RegionMaxSales rms ON rps.Region = rms.Region AND rps.SoldQuantity = rms.MaxSoldQuantity;
这个方法同样能拿到各地区销量最高的产品,也支持并列的情况。
内容的提问来源于stack exchange,提问作者magicalKhachapuri
相关产品推荐
相关产品推荐

