【问题标题】:Finding the 3 top selling products in each category查找每个类别中最畅销的 3 种产品
【发布时间】:2021-11-28 23:58:52
【问题描述】:

我正在尝试查找每个类别中最畅销的 3 种产品。但是我尝试的 SQL 并没有产生正确的结果。这是我做的事情:

产品表:

CREATE TABLE [dbo].[Products](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [name] [nvarchar](100) NOT NULL,
    [category] [nvarchar](100) NOT NULL,
 CONSTRAINT [PK_Products] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)
id name category
1 prod1 cat1
2 prod2 cat1
3 prod3 cat1
4 prod4 cat1
5 prod5 cat1
6 prod6 cat2
7 prod7 cat2
8 prod8 cat2
10 prod10 cat2

OrderItems 表:

CREATE TABLE [dbo].[OrderItems](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [prodID] [int] NOT NULL,
    [quantity] [int] NOT NULL,
 CONSTRAINT [PK_OrderItems] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)

ALTER TABLE [dbo].[OrderItems]  WITH CHECK ADD  CONSTRAINT [FK_OrderItems_Products] FOREIGN KEY([prodID])
REFERENCES [dbo].[Products] ([id])

ALTER TABLE [dbo].[OrderItems] CHECK CONSTRAINT [FK_OrderItems_Products]
id prodID quantity
1 1 10
2 2 6
3 2 6
4 4 3
5 3 2
6 6 10
7 7 1

我试过的 SQL:

select *
from (select p1.id, p1.category, (select sum(quantity) from OrderItems as oi where oi.prodID = p1.id) as sales
from Products as p1) as p2
where p2.sales >= (
    select distinct(sales)
    from (select p1.id, p1.category, (select sum(quantity) from OrderItems as oi where oi.prodID = p1.id) as sales
from Products as p1) as p3
    where p2.category = p3.category
    order by sales desc
    offset 2 rows fetch next 1 rows only)

预期结果:

id category sales
1 cat1 10
2 cat1 12
4 cat1 3
6 cat2 10
7 cat2 1

实际结果:

id category sales
1 cat1 10
2 cat1 12
4 cat1 3

查询中有什么错误?有没有更好的方法来达到这个结果?

【问题讨论】:

    标签: sql sql-server group-by sum window-functions


    【解决方案1】:

    您可以加入表格并汇总以获取每种产品的总销售额。
    还可以使用ROW_NUMBER()窗口函数根据产品的类别和总销售额排序来对每个产品进行排名和过滤:

    SELECT id, category, sales
    FROM (
      SELECT p.id, 
             MAX(category) category, 
             SUM(o.quantity) sales,
             ROW_NUMBER() OVER (PARTITION BY MAX(category) ORDER BY SUM(o.quantity) DESC) rn
      FROM Products p INNER JOIN OrderItems o
      ON o.prodID = p.id
      GROUP BY p.id
    ) t
    WHERE rn <= 3
    ORDER BY id;
    

    或者,先在OrderItems聚合,然后加入:

    SELECT id, category, sales
    FROM (
      SELECT p.id, 
             p.category, 
             o.sales,
             ROW_NUMBER() OVER (PARTITION BY p.category ORDER BY o.sales DESC) rn
      FROM Products p 
      INNER JOIN (
        SELECT prodID, SUM(quantity) sales
        FROM OrderItems
        GROUP BY prodID
      ) o ON o.prodID = p.id
    ) t
    WHERE rn <= 3
    ORDER BY id;
    

    请参阅demo

    【讨论】:

    • 感谢您提供具有行号的替代解决方案。另外,您能发现我发布的解决方案中的错误吗?
    • @JohnL。对于'cat2'offset 2 rows fetch next 1 rows only 返回的sales 的3d 值是null,因此条件等同于where p2.sales &gt;= null,因为与null 的任何比较都会返回null
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多