美好的一天,我在过去的一天里一直在努力解决这个问题,而我似乎无法理解这一点。
我的任务是从名为NORTHWIND的流行开源数据库中获取每个国家/地区销量最高的产品:https://northwinddatabase.codeplex.com
我能够进入这个阶段,这是我在SQL Server中的代码:
--Get most sold product for each country
WITH TotalProductsSold AS
(
SELECT od.ProductID, SUM(od.Quantity) AS TotalSold
FROM [Order Details] AS od
GROUP BY od.ProductID
)
SELECT MAX(TotalProductsSold.TotalSold) AS MostSoldQuantity, s.Country --,p.ProductName
FROM Products AS p
INNER JOIN TotalProductsSold
ON TotalProductsSold.ProductID = p.ProductID
INNER JOIN Suppliers AS s
ON s.SupplierID = p.SupplierID
GROUP BY s.Country
ORDER BY MostSoldQuantity DESC
这给了我以下结果:
这一切都很好,但我想找出MostSoldQuantity的产品名称。
非常感谢!
PS我发表评论--p.ProductName,我认为它会起作用,但它没有,如果有人可以解释我为什么GROUP BY不会自动允许我为那个很好的行派生产品名称答案 0 :(得分:1)
首先,从每个国家/地区销售的产品数量开始,而不仅仅是每个产品。然后对它们进行排名,只选RANK = 1。 有点像...
WITH
ProductQuantityByCountry AS
(
SELECT
s.CountryID,
p.ProductID,
SUM(od.Quantity) AS Quantity
FROM
[Order Details] AS od
INNER JOIN
Products AS p
ON p.ProductID = od.ProductID
INNER JOIN
Suppliers AS s
ON s.SupplierID = p.SupplierID
GROUP BY
s.CountryID,
p.ProductID
),
RankedProductQuantityByCountry
AS
(
SELECT
RANK() OVER (PARTITION BY CountryID ORDER BY Quantity DESC) AS countryRank,
*
FROM
ProductQuantityByCountry
)
SELECT
*
FROM
RankedProductQuantityByCountry
WHERE
countryRank = 1
请注意,一个国家/地区可能提供相同数量的不同产品,因此两个产品的排名均为= 1.查看ROW_NUMER()
和/或DENSE_RANK()
其他产品但与RANK()
的行为相似。
<强> 编辑: 强>
一个简单的练习来解释为什么SQL不允许你将Product.Name
放在最后的查询中是一个问题。
在这种情况下SQL应该做什么?
SELECT
MAX(TotalProductsSold.TotalSold) AS MostSoldQuantity,
MIN(TotalProductsSold.TotalSold) AS LeastSoldQuantity,
s.Country,
p.ProductName
FROM
blahblahblah
GROUP BY
s.Country
ORDER BY
MostSoldQuantity DESC
MIN
和 a MAX
的存在会使事情变得模棱两可。
您 可能清楚您要执行操作by country
,并且该操作是从该国家/地区挑选销售量最高的产品。但它实际上并不明确,对查询的微小更改可能会对任何推断的行为产生非常混乱的后果。相反,SQL的声明性语法提供了要解决的问题的非常清晰/明确/确定性的描述。
如果GROUP BY
子句中没有提及某个表达式,则无法对其进行SELECT
,而不对其进行汇总。这样就不会有什么含义或SQL引擎应该做什么。
要求您在查询的某个级别规定get the total sales per country per product
,然后您可以在查询的另一个级别干净地状态and then pick the highest ranked per country
。
这可能会让您觉得最终的查询时间长于&#34;应该&#34;是必要的。但它也会导致查询完全不明确,无论是将查询编译为执行计划,还是将来会读取您的代码的其他编码人员。