从 NORTHWIND 数据库中获取每个国家最畅销的产品

Get most sold product for each country from NORTHWIND database

大家好,过去一天我一直在为此苦苦挣扎,我似乎无法弄明白。

我的任务是从名为 NORTHWIND 的流行开源数据库中获取每个国家/地区最畅销的产品:https://northwinddatabase.codeplex.com

我能够到达这个阶段,这是我在 SQL 服务器中的代码:

--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 的产品名称。

非常感谢!

P.S 我发表评论 --p.ProductName 我认为它会起作用但它没有,如果有人能解释我为什么 GROUP BY 不自动允许我派生产品名称那行会很棒

首先,从销售产品的数量开始,每个国家/地区,而不仅仅是每个产品。然后对它们进行排名,只选择 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() and/or 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

MINMAX的存在使事情变得模棱两可。

可能很清楚你要执行一个操作by country并且那个操作是要挑选产品销量最高的那个国家。但它实际上并不明确,对查询的小改动可能会对任何推断的行为产生非常混乱的后果。相反,SQL 的声明性语法对要解决的问题提供了非常清晰/明确/确定的描述。

如果 GROUP BY 子句中未提及表达式,则不能 SELECT 它,而不对其进行聚合。这样一来,就意味着什么或 SQL 引擎应该做什么就没有歧义了。

通过要求您在查询的一个级别规定 get the total sales per country per product,然后您可以 干净地 在另一级别的查询中声明 and then pick the highest ranked per country

这可能会让您感觉最终查询的长度超过 "should" 是必要的。但它也会导致查询完全明确,既可以将查询编译为执行计划,也可以供将来阅读您的代码的其他编码人员使用。