Несколько запросов SQL-запросов неожиданные результаты - PullRequest
0 голосов
/ 15 сентября 2018

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

  • OrderYear - год, когда были размещены заказы
  • CustomerCategoryName - как показано в таблице Sales.CustomerCategories
  • CustomerCount - количество уникальных клиентов, размещающих заказы для каждого CustomerCategoryName и OrderYear
  • OrderCount - количество размещенных заказов для каждого CustomerCategoryName и OrderYear
  • Продажи - промежуточный итог из размещенных заказов, рассчитанный из Quantity и UnitPrice таблицы Sales.OrderLines
  • AverageSalesPerCustomer - средние продажи на клиента для каждого CustomerCategoryName и OrderYear

Результаты должны быть отсортированы в порядке возрастания, сначала по году заказа, а затем по названию категории клиента.

Моя попытка решения:

SELECT 
    CC.CustomerCategoryName,
    YEAR(O.OrderDate) AS OrderYear,
    COUNT(DISTINCT C.CustomerID) AS CustomerCount,
    COUNT(DISTINCT O.OrderID) AS OrderCount,
    SUM(OL.Quantity * OL.UnitPrice) AS Sales,
    SUM(OL.Quantity * OL.UnitPrice) / COUNT(DISTINCT C.CustomerID) AS AverageSalesPerCustomer
FROM
    Sales.CustomerCategories CC
INNER JOIN 
    Sales.Customers C ON C.CustomerCategoryID = CC.CustomerCategoryID
INNER JOIN 
    Sales.Orders O ON O.CustomerID = C.CustomerID
INNER JOIN 
    Sales.OrderLines OL ON OL.OrderID = O.OrderID
GROUP BY 
    CC.CustomerCategoryName, YEAR(O.OrderDate)
ORDER BY 
    YEAR(O.OrderDate), CC.CustomerCategoryName;

Мой OrderCount кажется правильным. Тем не менее, я не верю, что мои CustomerCount верны, а мои Sales и AverageSalesPerCustomer кажутся далёкими. Categories, у которых нет клиентов и заказов, не отображаются в моих результатах.

Является ли причина, по которой мои подсчеты отключены, а категории, в которых нет клиентов, отсутствуют, потому что они имеют только нулевые значения? Я считаю, что вопрос ищет все категории.

Я использую примеры таблиц WideWorldImporters от Microsoft.

Буду признателен за любую помощь, поскольку я новичок в SQL, и для меня очень сложно понять объединения.

1 Ответ

0 голосов
/ 15 сентября 2018

В настоящее время вы получаете только те данные, которые существуют в деталях заказа ... и не получаете ничего для несуществующих заказов. Обычно это выполняется с помощью внешних объединений вместо внутренних объединений и 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, чтобы выбрать только одну компанию ... и затем посмотреть детали ... . чтобы увидеть, если он проходит тест на запах. Намного легче оценить результаты, когда вы их ограничиваете. Точно так же вы можете добавить клиента в список выбора и внешнюю группировку по той же причине. Эксперимент - это ключ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...