SQL Server - 获取TOP 1产品的总计数

时间:2017-02-03 10:02:17

标签: sql sql-server

我需要能够找到客户下达的订单总数,还可以在一个查询中找到最佳产品。例如,在以下结构中,

CREATE TABLE #Cust (CustId INT, CustName VARCHAR(50))
CREATE TABLE #Product (ProductId INT, ProductName VARCHAR(10) )
CREATE TABLE #Orders (CustId INT, ProductId INT, OrderTaken BIT)

INSERT #Cust
        ( CustId, CustName )
VALUES  ( 1, 'Paul' ),
        ( 2, 'F' ),
        ( 3, 'Francis' )

INSERT #Product
        ( ProductId, ProductName )
VALUES  ( 1, 'Table' ),
        ( 2, 'Chair' )

INSERT #Orders
        ( CustId, ProductId, OrderTaken )
VALUES  ( 1, 1, 1 ),
        ( 1, 1, 1 ),
        ( 1, 2, 1 ),
        ( 2, 1, 1 )

我想出了一个查询,

SELECT * FROM #Cust AS C OUTER APPLY 
( 
    SELECT TOP 1 SQ.ProductId, SUM(SQ.TotalCount) AS TotalQty FROM 
    (
        SELECT O.ProductId, COUNT(*) TotalCount 
        FROM #Orders AS O WHERE O.CustId = C.CustId 
        GROUP BY O.CustId , O.ProductId
    ) SQ 
    GROUP BY SQ.ProductId 
) X

但是,这并没有给我我想要的结果,因为Paul给了我正确的ProductId,但仅仅是那个产品的数量。

我想要一个Query返回,

CustId  |   CustName    |   ProductId   |   TotalQty
--------+---------------+---------------+------------
1       |   Paul        |   1           |   3
2       |   F           |   1           |   1
3       |   Francis     |   NULL        |   NULL

5 个答案:

答案 0 :(得分:2)

一个选项是使用WITH TiES子句

Select Top 1 with ties 
       CustID
      ,CustName
      ,ProductId
      ,TotalQty
 From (
        Select  C.CustID
               ,C.CustName
               ,O.ProductId
               ,TotalQty = count(O.CustId) over (Partition By O.CustID)
               ,ProdCount = count(O.CustId) over (Partition By O.CustID,O.ProductID)
         From  #Cust  C
         Left  Join #Orders O on C.CustID=O.CustId
      ) A
 Order by Row_Number() over (Partition By CustID Order by ProdCount Desc) 

返回

CustID  CustName    ProductId   TotalQty
1       Paul        1           3
2       F           1           1
3       Francis     NULL        0

答案 1 :(得分:0)

尝试

SELECT c.*, ProductId, CustProdTotal, CustTotal 
FROM #Cust AS C 
OUTER APPLY (
    select top(1) with ties ProductId, CustProdTotal, CustTotal
    from (
        select *, count(OrderTaken) over() as CustTotal
                , count(OrderTaken) over(partition by ProductId) as CustProdTotal
        from #Orders o
        where O.CustId = C.CustId) x
    order by row_number() over(order by CustProdTotal desc) 
) z

答案 2 :(得分:0)

类似的问题已得到了很好的解释here

(在此受益:使用的常用连接概念)。 (缺点:对于大型记录,查询可能效率不高) 我已经为您的方案修改了解决方案

https://

答案 3 :(得分:0)

适用于SQL Server 2005及以上版本。

;with cte1 as (select c.custid, c.custname, o.productid, count(*) as TotalQty
from  #cust c
left join #orders o on c.custid=o.custid
left join #product p on p.productid=o.productid
group by c.custid, c.custname, o.productid)
,cte2 as (select custid,  max(TotalQty) as TopQty
from cte1
group by custid)
Select cte1.* 
from cte1
inner join cte2 on cte1.custid=cte2.custid and cte1.TotalQty=cte2.Topqty

答案 4 :(得分:-1)

如果您不能使用over子句,这将有效(显然,与over子句相比,工作量更多):

SELECT      custOrderAll.CustId
,           custOrderAll.CustName
,           MaxOrder.ProductId
,           MAX(custOrderAll.cntAll) TotalQty
FROM        (
                SELECT      c.CustId
                ,           c.CustName
                ,           COUNT(O.ProductId) cntAll
                FROM        #Cust AS C
                LEFT JOIN   #Orders AS O
                        ON  O.CustId = C.CustId
                GROUP BY    c.CustId
                ,           c.CustName
            ) custOrderAll
LEFT JOIN   (
                SELECT      custOrderMAX.CustId
                ,           custOrderMAX.CustName
                ,           custOrderMAX.ProductId
                FROM        (
                                SELECT      c.CustId
                                ,           c.CustName
                                ,           O.ProductId
                                ,           COUNT(O.ProductId) cntMax
                                FROM        #Cust AS C
                                LEFT JOIN   #Orders AS O
                                        ON  O.CustId = C.CustId
                                GROUP BY    c.CustId
                                ,           c.CustName
                                ,           O.ProductId
                            ) custOrderMAX
                INNER JOIN  (
                                SELECT      mxCnt.CustId
                                ,           mxCnt.CustName
                                ,           MAX(mxCnt.cntMax) mxCnt
                                FROM        (
                                                SELECT      c.CustId
                                                ,           c.CustName
                                                ,           O.ProductId
                                                ,           COUNT(O.ProductId) cntMax
                                                FROM        #Cust AS C
                                                LEFT JOIN   #Orders AS O
                                                        ON  O.CustId = C.CustId
                                                GROUP BY    c.CustId
                                                ,           c.CustName
                                                ,           O.ProductId
                                            ) mxCnt
                                GROUP BY    mxCnt.CustId
                                ,           mxCnt.CustName
                            ) custOrderMAXCnt
                        ON  custOrderMAXCnt.CustId = custOrderMAX.CustId
                        AND custOrderMAXCnt.mxCnt = custOrderMAX.cntMax
            ) MaxOrder
        ON  MaxOrder.CustId = custOrderAll.CustId
        AND MaxOrder.CustName = custOrderAll.CustName
GROUP BY    custOrderAll.CustId
,           custOrderAll.CustName
,           MaxOrder.ProductId

结果:

+--------+----------+-----------+----------+
| CustId | CustName | ProductId | TotalQty |
+--------+----------+-----------+----------+
|      1 | Paul     | 1         |        3 |
|      2 | F        | 1         |        1 |
|      3 | Francis  | NULL      |        0 |
+--------+----------+-----------+----------+