COUNT DISTINCT и оконные функции

Мы без проблем можем посчитать общее количество ПК для каждого производителя, а также количество уникальных моделей данного производителя в таблице 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;
mssql
🚫
[[ error ]]
[[ column ]]
[[ value ]]
makermodelsunique_models
A82
B31
E11

Если нам требуется получить детальную информацию о каждой модели, наряду с их общим количеством для каждого производителя, то можно использовать оконную функцию:

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;
mssql
🚫
[[ error ]]
[[ column ]]
[[ value ]]
makermodelpricemodels
A1232600,008
A1232400,008
A1232350,008
A1232350,008
A1233600,008
A1233950,008
A1233980,008
A1233970,008
B1121850,003
B1121850,003
B1121850,003
E1260350,001

Теперь представим, что нам требуется дополнить эту информацию количеством уникальных моделей. Естественная попытка

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;
mssql
🚫
[[ error ]]
[[ column ]]
[[ value ]]
терпит неудачу:

Использование ключевого слова 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;
mssql
🚫
[[ error ]]
[[ column ]]
[[ value ]]
makermodelmodelsunique_models
A123282
A123282
A123282
A123282
A123382
A123382
A123382
A123382
B112131
B112131
B112131
E126011

Использование 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;
mssql
🚫
[[ error ]]
[[ column ]]
[[ value ]]

Здесь мы воспользовались тем фактом, что последнее ранговое значение - max(drnk) - оказывается равным числу уникальных моделей.