2009-07-08 5 views
3

У меня есть две таблицы, одна со всеми моими ветвями и одна со всеми моими продажами. Таблица продаж также содержит идентификатор торгового представителя, идентификатор филиала, месяц и год.T-SQL, нулевая сумма для отсутствия совпадения при соединении

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

SELECT 
    s.Month, 
    b.BranchName, 
    SUM(s.InvoiceAmount) AS 'Sales' 
FROM 
    Branch b 
INNER JOIN 
    Sales s ON s.BranchID = b.BranchID 
WHERE 
    s.Year = 2008 
AND 
    s.SalesRepID= 11 
GROUP BY 
    s.Month, 
    b.BranchName 
ORDER BY 
    s.Month, 
    b.BranchName 
+0

Вам не хватает s.Month из списка SELECT? – pjp

+0

Моя ошибка, да, s.Month находится в SELECT – staterium

+0

(исправлено в OP) – staterium

ответ

4

Вам нужно будет добавить «отсутствующие» данные, чтобы присоединиться к нему.

SELECT 
    b.BranchName, 
    SUM(ISNULL(s.InvoiceAmount, 0)) AS 'Sales', 
    s.Month 
FROM 
    Branch b 
    LEFT OUTER JOIN (
      SELECT 
     b.BranchID AS BranchID 
     , s.SalesRepID AS SalesRepID 
     , Months.Month AS Month 
     , Years.Year AS Year 
     , 0 AS InvoiceAmount 
     FROM 
      Sales s 
      CROSS JOIN (
      SELECT 1 AS Month 
      UNION ALL SELECT 2 
      UNION ALL SELECT 3 
      UNION ALL SELECT 4 
      UNION ALL SELECT 5 
      UNION ALL SELECT 6 
      UNION ALL SELECT 7 
      UNION ALL SELECT 8 
      UNION ALL SELECT 9 
      UNION ALL SELECT 10 
      UNION ALL SELECT 11 
      UNION ALL SELECT 12 
      ) Months 
      CROSS JOIN (
      SELECT 2007 AS Year 
      UNION ALL SELECT 2008 
      UNION ALL SELECT 2009 
      ) Years 
      CROSS JOIN Branch b 
     UNION ALL SELECT 
     s.BranchID AS BranchID 
     , s.SalesRepID AS SalesRepID 
     , s.Month AS Month 
     , s.Year AS Year 
     , s.InvoiceAmount AS InvoiceAmount 
     FROM Sales s  
    )s ON s.BranchID = b.BranchID  
WHERE 
    s.Year = 2008 
    AND s.SalesRepID= 11 
GROUP BY 
    s.Month, 
    b.BranchName 
ORDER BY 
    b.BranchName, 
    s.Month 
+0

Я собирался опубликовать что-то подобное – pjp

+1

рад слышать, что я не одинок в том, как я интерпретировал вопрос. Все остальные ответы, похоже, сосредоточены на значениях NULL в InvoiceAmount. Я сомневаюсь, что это означало OP. –

+0

Спасибо Lieven, что работает (вроде). Теперь я получаю 0 значений за месяцы, в которых у rep не было продаж в этой ветке, но запрос в целом возвращает только те филиалы, где у репутации были продажи в какой-то момент года. – staterium

2

Вам нужно сделать LEFT JOIN к продажам, чтобы вернуться даже повторений, которые не имеют каких-либо записей в Таблица продаж.

+0

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

+0

-1 Существует предложение where на s.SalesRepId, и поэтому внешнее соединение слева на Sales будет бессмысленным. – pjp

1

Если запрос возвращает NULL, вы можете использовать один из методов сливающихся: COALESCE(SUM(...), 0) возвратят первое ненулевое значение в списке ...

+0

Не должно ли сливаться внутри суммы. Или сумма может суммироваться по значениям NULL. Я верю, что это вызывает предупреждение в SQL-сегменте. – pjp

+0

Предупреждение: значение Null исключается агрегатом или другой операцией SET. (1 ряд (-ых) затронутых) – pjp

0

Я изменил джойн от внутреннего к левым внешним и добавил функция ISNULL для филиалов без продаж.

SELECT 

    b.BranchName, 
    s.Month, 
    SUM(ISNULL(s.InvoiceAmount,0)) AS 'Sales' 
FROM 
    Branch b 
LEFT JOIN 
    Sales s ON s.BranchID = b.BranchID 
WHERE 
    s.Year = 2008 
AND 
    s.SalesRepID= 11 
GROUP BY 
    s.Month, 
    b.BranchName 
ORDER BY 
    s.Month, 
    b.BranchName 
+0

Вопрос запрашивает продажи по месяцам, даже если в течение определенного месяца продажи отсутствуют. Этот запрос возвращает результаты за весь год. – pjp

+0

Это не изменило моего результата. – staterium

0

Вы должны использовать левое соединение и IsNull получить сумму прямо:

SELECT b.BranchName 
, SUM(isnull(s.InvoiceAmount, 0)) AS 'Sales' 
FROM  Branch b 
LEFT JOIN Sales s ON s.BranchID = b.BranchID 
GROUP BY  s.Month, b.BranchName 
ORDER BY  s.Month, b.BranchName 

Вам все еще нужно сделать немного больше работы с ним, чтобы получить месяцев, показывая слишком, если продавец имеет нет продаж за определенный месяц.