【问题标题】:Top 3 rows per country每个国家/地区的前 3 行
【发布时间】:2014-12-02 05:51:27
【问题描述】:

我制作了一份“在每个国家/地区销售了哪些产品以及销售了多少产品”的报告。我正在使用 Northwind 数据库,SQL Server 2012。

以下是代码:

SELECT 
    o.ShipCountry AS 'Country',od.ProductID,
    p.ProductName, p.UnitPrice,
    SUM(od.Quantity) AS 'Number of Units Sold'
FROM 
    Products p
INNER JOIN 
    [Order Details] od ON od.ProductID = p.ProductID
INNER JOIN 
    Orders o ON o.OrderID = od.OrderID
GROUP BY 
    p.ProductName, od.ProductID, p.UnitPrice, o.ShipCountry
ORDER BY 
    o.ShipCountry, 'Number of Units Sold' DESC

结果显示超过 900 行,每个国家/地区大约有 10 到 20 行:

但我想更上一层楼,现在我想生产“每个国家/地区销售的前 3 名产品” 所以我尝试了ROW_NUMBER() OVER (PARTITION BY,但我在使用Row_NUMBER()时很笨拙

以下是我的错误代码:

WITH CTE AS
(
   SELECT 
      o.ShipCountry AS 'Country',od.ProductID,
      p.ProductName, p.UnitPrice,
      SUM(od.Quantity) AS 'Number of Units Sold',
      ROW_NUMBER() OVER (PARTITION BY o.ShipCountry ORDER BY ('Number of Units Sold') DESC) AS 'Number of Units Sold'
   FROM 
      Products p
   INNER JOIN 
      [Order Details] od ON od.ProductID = p.ProductID
   INNER JOIN 
      Orders o ON o.OrderID = od.OrderID)
SELECT 
    'Country', ProductID, 
     ProductName, UnitPrice, 'Number of Units Sold'
FROM 
    CTE 
WHERE 
    'Number of Units Sold' < 4
GROUP BY 
    p.ProductName, od.ProductID, p.UnitPrice, o.ShipCountry
ORDER BY 
    o.ShipCountry DESC

【问题讨论】:

    标签: sql sql-server tsql sql-server-2012 row-number


    【解决方案1】:

    试试这个:

    WITH CTE AS 
    (
        SELECT 
            o.ShipCountry, od.ProductID,
            p.ProductName, p.UnitPrice,
            SUM(od.Quantity) AS UnitsSold,
            RowNum = ROW_NUMBER() OVER (PARTITION BY o.ShipCountry ORDER BY SUM(od.Quantity) DESC)
        FROM 
            Products p
        INNER JOIN 
            [Order Details] od ON od.ProductID = p.ProductID
        INNER JOIN 
            Orders o ON o.OrderID = od.OrderID
        GROUP BY 
            p.ProductName, od.ProductID, p.UnitPrice, o.ShipCountry
    )
    SELECT * 
    FROM CTE
    WHERE CTE.RowNum <= 3
    

    基本上,在 CTE 中,您可以定义您想要的列 - 请注意:不要使用列名称带有空格之类的东西!在屏幕上进行漂亮的演示,但在查询中很难使用!

    然后添加 ROW_NUMBER(),它将从 1 开始为每个国家/地区的每个条目编号。

    最后,您从 CTE 中进行选择,并且您只选择带有 RowNum &lt;= 3 ==> 的那些行成为每个国家/地区的前 3 名。

    【讨论】:

    • 感谢您提供易于理解的解决方案和清晰的解释!那么 GROUP BY 子句进入 CTE 吗?
    • @user3601310: 是的,既然你在 CTE 中有 SUM 函数,你还需要在里面有 GROUP BY..
    【解决方案2】:
    ;with CTE as(
    SELECT o.ShipCountry AS 'Country',
           od.ProductID,
           p.ProductName,
           p.UnitPrice,
           SUM(od.Quantity) AS 'Number of Units Sold'
    FROM Products p
    INNER JOIN [Order Details] od
    ON od.ProductID=p.ProductID
    INNER JOIN Orders o
    ON o.OrderID=od.OrderID
    GROUP BY p.ProductName, od.ProductID, p.UnitPrice, o.ShipCountry
    ) 
    ,CTE2 as
    (    Select 
           CTE.Country,
           CTE.ProductID,
           CTE.ProductName,
           CTE.UnitPrice,
           CTE.[Number of Units Sold],
           ROW_NUMBER() OVER (PARTITION BY CTE.Country 
           ORDER BY CTE.[Number of Units Sold] DESC) AS rownum
         from CTE
    )
    select CTE2.Country,
           CTE2.ProductID,
           CTE2.ProductName,
           CTE2.UnitPrice,
           CTE2.[Number of Units Sold]
    FROM CTE2 
    WHERE CTE2.rownum<4
    ORDER BY CTE2.Country, CTE2.[Number of Units Sold] DESC   
    

    【讨论】:

    • 感谢您花时间为我提供解决方案。您的解决方案运行良好,但我很抱歉这对我来说有点复杂......但我真的很感激!
    【解决方案3】:

    试试这个:

    SELECT Country, ProductID, 
    ProductName,UnitPrice,Number_of_Units_Sold
    FROM 
    ( 
    SELECT o.ShipCountry AS Country, od.ProductID as ProductID,
    p.ProductName as ProductName, p.UnitPrice as UnitPrice,
    SUM(od.Quantity) AS Number_of_Units_Sold,
    ROW_NUMBER() OVER (PARTITION BY o.ShipCountry ORDER BY (SUM(od.Quantity)) DESC) AS MYRANK
    
    FROM Products p
    INNER JOIN [OrderDetails] od
    ON od.ProductID=p.ProductID
    INNER JOIN Orders o
    ON o.OrderID=od.OrderID
    
    GROUP BY o.ShipCountry, p.ProductName, od.ProductID, p.UnitPrice, o.ShipCountry
    
    ) tmp
    where MYRANK <= 3
    ORDER BY Country, Number_of_Units_Sold DESC
    

    【讨论】:

    • 感谢您给我一个解决方案和您花费的时间,但不知何故它有一些错误......但我认为这只是小错误:) 无论如何,我真的很感谢你的回答!
    猜你喜欢
    • 2021-07-14
    • 2023-03-05
    • 1970-01-01
    • 2011-08-25
    • 2019-06-24
    • 1970-01-01
    • 1970-01-01
    • 2015-04-06
    • 1970-01-01
    相关资源
    最近更新 更多