Вы должны быть в состоянии убрать свой "грязный" ответ так:
select Category1, Category2, count(distinct ItemId)
from ItemList
group by Category1, Category2
UNION ALL
select Category1, null, count(distinct ItemId)
from ItemList
group by Category1
UNION ALL
select null, Category2, count(distinct ItemId)
from ItemList
group by Category2
UNION ALL
select null, null, count(distinct ItemId)
from ItemList
Затем я выбрал другой вариант:
select IL1.Category1, IL1.Category2, count(distinct ItemId)
from (
select Category1, Category2
from ItemList
group by Category1, Category2
with cube
) IL1
join ItemList IL2 on (IL1.Category1=IL2.Category1 and IL1.Category2=IL2.Category2)
or (IL1.Category1 is null and IL1.Category2=IL2.Category2)
or (IL1.Category2 is null and IL1.Category1=IL2.Category1)
or (IL1.Category1 is null and IL1.Category2 is null)
group by IL1.Category1, IL1.Category2
Эффективность может варьироваться в зависимости от индексов, количества группируемых столбцов и т. Д. Для написанной мной тестовой таблицы sub-select и join (в отличие от Unions) были несколько лучше. У меня нет доступа к экземпляру MSSQL 2000 (я тестировал на экземпляре 2005 года), но я не думаю, что здесь что-то недопустимо.
UPDATE
Еще лучший вариант, особенно если вы группируете по более чем 2 столбцам (если вы группируете по 8 столбцам, приведенный выше код потребует 256 предложений объединения, чтобы перехватить все нулевые комбинации!):
select IL1.Category1, IL1.Category2, count(distinct ItemId)
from (
select Category1, Category2
from ItemList
group by Category1, Category2
with cube
) IL1
inner join ItemList IL2 on isnull(IL1.Category1,IL2.Category1)=IL2.Category1
and isnull(IL1.Category2,IL2.Category2)=IL2.Category2
group by IL1.Category1, IL1.Category2