Я собирался представить в значительной степени то же самое, что @Squirrell только с общим выражением таблицы [CTE], а не с производной таблицей. Поэтому я не буду дублировать это, но есть некоторые точки обучения по вашему запросу. Первый - IMPLICIT JOINS
, такие как FROM Bill_Item, Bill
, действительно легко иметь ожидаемые последствия (один из многих вопросов: Queries that implicit SQL joins can't do?). Далее для вычисленного столбца вы можете сделать это в OUTER APPLY
или CROSS APPLY
, что является очень полезной техникой.
Таким образом, вы могли бы заново написать свой метод следующим образом:
SELECT *
FROM
Product p
OUTER APPLY (SELECT TOP 1 b.client_id
FROM
Bill_Item bi
INNER JOIN Bill b
ON bi.bill_id = b.bill_id
WHERE
bi.product_id = p.product_id
GROUP BY
b.client_id
ORDER BY
COUNT(*) DESC) c
И чтобы показать вам, как ответ Squirell может еще включать в себя продукты, которые никогда не были проданы все, что вам нужно сделать, это присоединиться к продукции и LEFT JOIN к другие таблицы:
;WITH cte AS (
SELECT
p.product_id
,b.client_id
,ROW_NUMBER() OVER (PARTITION BY p.product_id ORDER BY COUNT(*) DESC) as RowNumber
FROM
Product p
LEFT JOIN Bill_Item bi
ON p.product_id = bi.product_id
LEFT JOIN Bill b
ON bi.bill_id = b.bill_id
GROUP BY
p.product_id
,b.client_id
)
SELECT *
FROM
cte
WHERE
RowNumber = 1
Методы, используемые в некоторых из них, которые являются полезными.
- КТР
- ОТНОСИТЬСЯ (Outer & Cross)
- Функции окна
Какую версию SQL вы используете? –
SQL Server 2012 –
Не уверен, будет ли он оптимизировать запрос, но рекомендуется использовать 'JOIN', поэтому ваш запрос может быть изменен на' FROM Bill_Item INNER JOIN Bill ON Bill_Item.product_id = p.product_id и Bill_Item.bill_id = Bill.bill_id' Вы можете использовать 'SHOWPLAN' для проверки плана выполнения. –