从NORTHWIND数据库

时间:2017-11-27 13:30:31

标签: sql sql-server database group-by northwind

美好的一天,我在过去的一天里一直在努力解决这个问题,而我似乎无法理解这一点。

我的任务是从名为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

这给了我以下结果:

enter image description here

这一切都很好,但我想找出MostSoldQuantity的产品名称。

非常感谢!

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

1 个答案:

答案 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;是必要的。但它也会导致查询完全不明确,无论是将查询编译为执行计划,还是将来会读取您的代码的其他编码人员。