SQL и "Борей"

У меня есть запрос, где я могу найти все продукты, всех клиентов, которые купили каждый продукт и количество.

select OD.ProductID, OD.Quantity, O.CustomerID
from dbo.[Order Details] OD inner join dbo.Orders O on OD.OrderID = O.OrderID
Order by OD.ProductID ASC, OD.Quantity DESC

Но что мне нужно, так это узнать, какой клиент купил больше всего каждого продукта. Как мне это сделать?


person Walther Emilio Carrasco    schedule 23.03.2017    source источник
comment
Какая версия SQL Server? В более поздних версиях вы можете использовать RANK() для решения этой проблемы.   -  person Nick.McDermaid    schedule 23.03.2017
comment
SQL Server 2014   -  person Walther Emilio Carrasco    schedule 23.03.2017


Ответы (1)


Вы можете использовать top 1 with ties с оконной функцией rank:

select top 1 with ties OD.ProductID,
    OD.Quantity,
    O.CustomerID
from dbo.[Order Details] OD
inner join dbo.Orders O on OD.OrderID = O.OrderID
order by rank() over (
        partition by OD.ProductID order by OD.Quantity desc
        );

Вышеприведенное вернет несколько строк для каждого productId, если есть несколько клиентов с максимальным количеством заказанного для этого продукта.

Если вы хотите получить только одну строку, вы можете использовать row_number:

select top 1 with ties OD.ProductID,
    OD.Quantity,
    O.CustomerID
from dbo.[Order Details] OD
inner join dbo.Orders O on OD.OrderID = O.OrderID
order by row_number() over (
        partition by OD.ProductID order by OD.Quantity desc
        );

Вы также можете сделать это без top:

select *
from (
    select OD.ProductID,
        OD.Quantity,
        O.CustomerID,
        row_number() over (
            partition by OD.ProductID order by OD.Quantity desc
            ) as rn
    from dbo.[Order Details] OD
    inner join dbo.Orders O on OD.OrderID = O.OrderID
    ) t
where rn = 1;
person Gurwinder Singh    schedule 23.03.2017
comment
Есть ли способ сделать это с помощью подзапроса? Я никогда не использовал ранг или связи - person Walther Emilio Carrasco; 23.03.2017
comment
@WaltherEmilioCarrasco - оконные функции отлично подходят для решения таких проблем. Если вы не хотите использовать top, см. третий запрос в обновленном ответе. - person Gurwinder Singh; 23.03.2017
comment
Вы должны воспользоваться этой возможностью, чтобы научиться использовать оконные функции. - person Nick.McDermaid; 23.03.2017