Мы без проблем можем посчитать общее количество ПК для каждого производителя, а также количество уникальных моделей данного производителя в таблице PC:
Консоль
SELECT maker, COUNT ( *) models, COUNT ( DISTINCT pc.model) unique_models
FROM product p JOIN pc ON p.model=pc.model
GROUP BY maker
ORDER BY maker;
maker
models
unique_models
A 8 2
B 3 1
E 1 1
Если нам требуется получить детальную информацию о каждой модели, наряду с их общим количеством для каждого производителя, то можно использовать оконную функцию:
Консоль
SELECT maker, pc.model,pc.price,
COUNT ( *) over( partition BY maker) models
FROM product p JOIN pc ON p.model=pc.model
ORDER BY maker, pc.model;
maker
model
price
models
A 1232 600,00 8
A 1232 400,00 8
A 1232 350,00 8
A 1232 350,00 8
A 1233 600,00 8
A 1233 950,00 8
A 1233 980,00 8
A 1233 970,00 8
B 1121 850,00 3
B 1121 850,00 3
B 1121 850,00 3
E 1260 350,00 1
Теперь представим, что нам требуется дополнить эту информацию количеством уникальных моделей. Естественная попытка
Консоль
SELECT maker, pc.model,pc.price,
COUNT ( *) over( partition BY maker) models,
COUNT ( DISTINCT pc.model) over( partition BY maker) unique_models
FROM product p JOIN pc ON p.model=pc.model
ORDER BY maker, pc.model;
терпит неудачу:
Использование ключевого слова DISTINCT не допускается с предложением OVER.
Сообщение об ошибке ясно описывает проблему. Вопрос в том, как её обойти.
Использование подзапроса
Консоль
WITH cte AS
( SELECT maker, pc.model,pc.price,
COUNT ( *) over( partition BY maker) models
FROM product p JOIN pc ON p.model=pc.model)
SELECT maker, model, models,
( SELECT COUNT ( DISTINCT model)
FROM cte t WHERE t.maker=cte.maker) unique_models
FROM cte
ORDER BY maker,model;
maker
model
models
unique_models
A 1232 8 2
A 1232 8 2
A 1232 8 2
A 1232 8 2
A 1233 8 2
A 1233 8 2
A 1233 8 2
A 1233 8 2
B 1121 3 1
B 1121 3 1
B 1121 3 1
E 1260 1 1
Использование DENSE_RANK
Консоль
WITH cte AS
( SELECT maker, pc.model,pc.price,
COUNT ( *) over( partition BY maker) models,
DENSE_RANK( ) over( partition BY maker ORDER BY pc.model) drnk
FROM product p JOIN pc ON p.model=pc.model)
SELECT maker, model, price, models,
MAX ( drnk) over( partition BY maker) unique_models FROM cte
ORDER BY maker, model;
Здесь мы воспользовались тем фактом, что последнее ранговое значение - max(drnk) - оказывается равным числу уникальных моделей.