【问题标题】:Get most sold product for each country from NORTHWIND database从 NORTHWIND 数据库中获取每个国家/地区最畅销的产品
【发布时间】:2017-11-27 13:30:31
【问题描述】:

大家好,过去一天我一直在努力解决这个问题,但我似乎无法弄清楚。

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

非常感谢!

【问题讨论】:

  • 我假设您知道您提出的答案不起作用,因为您已将其删除。重要的原因MAX(productID)MAX(TotalSold)完全没有关系,它们是独立计算的。 (您创建数据集,在数据集中创建组,在每个组中您获得最高的 TotalSold 并分别获得 ProductID 的最高值。 没有 SQL 表达式“获取关联的 productID MAX(TotalSold) 的结果是在 SELECT 列表中的另一个表达式中计算的`")。
  • 是的,当我检查 productID 与最畅销的数量不匹配时,我就意识到
  • 我现在正在查看您的答案,谢谢您的时间:)

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


【解决方案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

请注意,一个国家/地区可能提供 相同 数量的不同产品,因此两种产品的 rank = 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 的存在MAX 使事情变得模棱两可。

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

如果GROUP BY 子句中未提及某个表达式,则不能在不聚合的情况下SELECT 它。这样就不会对 SQL 引擎的含义或应该做什么产生歧义。

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

这可能会让您觉得查询的长度超出了“应该”是必要的。但它也会产生完全明确的查询,无论是为了将查询编译为执行计划,还是对于其他将在未来阅读您的代码的编码人员。

【讨论】:

  • 非常感谢!我得到了它的工作,我使用了你的想法。我仍然是 SQL 的初学者,我不知道排名函数,我认为必须有一个更简单的解决方案,而无需超越 GROUP BY 和聚合函数,但到目前为止,你的答案是唯一能解决我的问题而不是以一种糟糕的方式海事组织。谢啦 ! :)
猜你喜欢
  • 1970-01-01
  • 2021-08-19
  • 2020-01-28
  • 1970-01-01
  • 2020-07-30
  • 1970-01-01
  • 1970-01-01
  • 2016-03-03
  • 2020-03-06
相关资源
最近更新 更多