【问题标题】:Trying to Find Most Popular Product试图找到最受欢迎的产品
【发布时间】:2014-12-18 02:11:04
【问题描述】:

我正在尝试编写一个查询,根据他们购买的所有产品的数量来吸引前 5 位客户。没问题。但除此之外,我还需要为这 5 位客户中的每一个找到最受欢迎的产品。

我想我可以通过查看他们购买最多的产品来做到这一点(所以 productID 的数量是最大数量),但我不太确定如何获取 productID。有任何想法吗?我对这一切都错了吗?谢谢!

select top 5 c.CustomerID, sum(sod.orderqty) AS 'Amount Purchased', 
max(sod.orderqty) AS 'Most Purchased'   
from Sales.Customer c
inner join Sales.SalesOrderHeader soh on soh.CustomerID = c.CustomerID
inner join Sales.SalesOrderDetail sod on sod.SalesOrderID = soh.SalesOrderID
inner join Production.Product p on p.ProductID = sod.ProductID
group by c.CustomerID
order by 'Amount Purchased' desc

我尝试了下面的查询,但由于某种原因,将 p.name 包含在 group by 中完全超出了最大值。例如,在这个查询中,'Most Purchased' 应该是 20,但它显示为 18(这是 2nd-next max.)

select top 5 soh.CustomerID, sum(sod.orderqty) AS 'Amount Purchased'
, max(sod.orderqty) AS 'Most Purchased', p.name 
from Sales.SalesOrderHeader soh 
inner join Sales.SalesOrderDetail sod on sod.SalesOrderID = soh.SalesOrderID
inner join Production.Product p on p.ProductID = sod.ProductID
where soh.CustomerID = 29705
group by soh.CustomerID, p.name
order by 'Amount Purchased' desc

【问题讨论】:

    标签: sql sql-server


    【解决方案1】:

    我们可以分两个阶段进行。我正在使用 SQL Server 2008。

    首先像你一样找到前 5 名客户:

    WITH
    CTE_TopCustomers
    AS
    (
        select top (5)
            c.CustomerID
            , sum(sod.orderqty) AS 'Amount Purchased'
        from
            Sales.Customer c
            inner join Sales.SalesOrderHeader soh on soh.CustomerID = c.CustomerID
            inner join Sales.SalesOrderDetail sod on sod.SalesOrderID = soh.SalesOrderID
            inner join Production.Product p on p.ProductID = sod.ProductID
        group by
            c.CustomerID
        order by 'Amount Purchased' desc
    )
    

    然后为每个客户找到最受欢迎的产品。请参阅CROSS APPLY 中的子查询。这里的“最受欢迎”是指客户总共购买最多的产品。比如说,如果客户在一天购买了 10 件带有ID=1 的产品,第二天又购买了 20 件带有 ID=1 的相同产品,那么总和就是 30。如果同一客户购买了 25 件其他产品ID=2 一天,那么该客户最受欢迎的产品将是具有ID=1 和总共 30 个单位的产品。

    如果您想在本例中选择ID=2 作为最受欢迎的产品,请将CROSS APPLY 中的SUM 更改为MAX

    SELECT
        CTE_TopCustomers.CustomerID
        ,CTE_TopCustomers.[Amount Purchased]
        ,CTE_Products.ProductID
        ,CTE_Products.ProductName
        ,CTE_Products.SumCustomerProductQty
    FROM
        CTE_TopCustomers
        CROSS APPLY
        (
            SELECT TOP (1)
                p.ProductID
                ,p.name AS ProductName
                ,SUM(sod.orderqty) AS SumCustomerProductQty
            FROM
                Sales.SalesOrderHeader soh on soh.CustomerID = CTE_TopCustomers.CustomerID
                inner join Sales.SalesOrderDetail sod on sod.SalesOrderID = soh.SalesOrderID
                inner join Production.Product p on p.ProductID = sod.ProductID
            GROUP BY
                p.ProductID
                ,p.name
            ORDER BY SumCustomerProductQty DESC
        ) AS CTE_Products
    ORDER BY [Amount Purchased] DESC;
    

    对于最终查询,只需将两个代码块放在一起即可。

    【讨论】:

    • 我在“FROM Sales.SalesOrderHeader soh on soh.customerID = CTE_TopCustomers.CustomerID”的交叉应用中遇到错误。它在“on”附近显示不正确的语法。我所做的似乎都无法解决它......
    • 如果没有实际的表和在我编写时运行查询的可能性,很难正确编写所有内容。下次您提出此类问题时,请提供代码以使用示例数据创建示例表。无论如何,我很高兴它对你有用。
    【解决方案2】:

    按产品进行中间聚合:

    select top 5 CustomerId, sum(AmountPurchased) as AmountPurchased,
           max(AmountPurchased) as maxAmountPurchased,
           max(case when seqnum = 1 then productId end) as MostPurchased
    from (select c.CustomerID, p.ProductId, sum(sod.orderqty) AS AmountPurchased, 
                 row_number() over (partition by c.CustomerId order by sum(sod.orderqty) desc) as seqnum
          from Sales.Customer c inner join
               Sales.SalesOrderHeader soh
               on soh.CustomerID = c.CustomerID inner join
               Sales.SalesOrderDetail sod
               on sod.SalesOrderID = soh.SalesOrderID inner join
               Production.Product p
               on p.ProductID = sod.ProductID
          group by c.CustomerID, ProductId
         ) cp
    group by CustomerId
    order by AmountPurchased desc;
    

    请注意,关于最大金额,这与您的查询略有不同。此版本提供了整个产品级别的最大值。您可以通过在子查询中使用 max() 来获取您的版本,但这似乎是您真正想要的。

    【讨论】:

    • 嗯,我试过了,但数字似乎不正确。查看表本身,1 个客户的 max(orderqty) 为 20(因此他订购了 20 个 productID = 1),但在运行您的查询时,它显示他订购了 180 个。
    • @Michelle 。 . .在这种情况下,您的连接可能是通过沿两个不同维度连接来增加行数。您需要修复连接以获得您想要的。
    猜你喜欢
    • 2021-02-20
    • 1970-01-01
    • 2021-07-02
    • 2022-11-12
    • 1970-01-01
    • 2012-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多