每个国家排名前3行

时间:2014-12-02 05:51:28

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

我已经制作了一份报告"在每个国家/地区销售了多少产品和#34;我正在使用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行:

The result is

但我想把它提升一个档次,现在我想生产"每个国家销售的前三种产品" 所以我尝试了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

3 个答案:

答案 0 :(得分:2)

试试这个:

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 <= 3 ==&gt;的行。每个国家的前三名。

答案 1 :(得分:1)

;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   

答案 2 :(得分:0)

试试这个:

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