В настоящее время вы получаете только те данные, которые существуют в деталях заказа ... и не получаете ничего для несуществующих заказов. Обычно это выполняется с помощью внешних объединений вместо внутренних объединений и isnull(possiblyNullValue,replacementValue)
.
Кроме того, когда вы группируете по годам (o.OrderDate), ваше объединение для заказов не различается по годам ... возможно, получая данные за все годы для каждого клиента за каждый отчетный период.
Итак, давайте сначала разберем отчетный период ... и убедимся, что мы основываем наши результаты на этом:
select distinct year(o.OrderDate) from Sales.Orders
Но на самом деле вам нужны все категории и все годы ... чтобы вы могли объединить их, чтобы получить реальную основу:
select
cc.CustomerCategoryId,
cc.CustomerCategoryName,
year(o.OrderDate)
from
Sales.Orders o
cross join
Sales.CustomerCategories cc
group by
cc.CustomerCategoryId,
cc.CustomerCategoryName,
year(o.OrderDate)
Теперь вы хотите включить этот беспорядок в оставшийся запрос. Есть два способа сделать это ... один - использовать предложение with
... но иногда проще просто заключить базовый запрос в скобки и использовать его, как если бы это была таблица:
select
cy.CustomerCategoryName,
cy.CalendarYear,
count(distinct c.CustomerId) CustomerCount,
isnull(sum(ol.UnitPrice * ol.Quantitiy),0.0) Sales,
isnull(sum(ol.UnitPrice * ol.Quantitiy) / count(distinct c.CustomerId),0.0) AverageSalesPerCustomer
from
(
select
cc.CustomerCategoryId,
cc.CustomerCategoryName,
year(o.OrderDate) CalendarYear --> must name calc'd cols in virtual tables
from
Sales.Orders o
cross join
Sales.CustomerCategories cc
group by
cc.CustomerCategoryId,
cc.CustomerCategoryName,
year(o.OrderDate)
) as cy --> cy is the "Category Years" virtual table
left outer join
Sales.Customers c
on cy.CustomerCategoryId = c.CustomerCategoryId
left outer join
Sales.Orders o
on
c.CustomerId = o.CustomerId --> join on customer and year
and --> to make sure we're only getting
cy.CalendarYear = Year(o.OrderDate) --> orders in the right year
left outer join
Sales.OrderLines ol
on o.OrderId = ol.OrderId
group by
cy.CalendarYear,
cy.CustomerCategoryName
order by
cy.CalendarYear,
cy.CustomerCategoryName
Между прочим ... не стесняйтесь связываться с вашими запросами, чтобы выбрать какое-то подмножество ... например, вы можете добавить предложение where, чтобы выбрать только одну компанию ... и затем посмотреть детали ... . чтобы увидеть, если он проходит тест на запах. Намного легче оценить результаты, когда вы их ограничиваете. Точно так же вы можете добавить клиента в список выбора и внешнюю группировку по той же причине. Эксперимент - это ключ.