T-SQL, a somma zero per alcuna corrispondenza su unirsi
-
11-09-2019 - |
Domanda
Ho due tavoli, uno con tutti i miei rami, e uno con tutte le mie vendite. La tabella di vendita contiene anche un ID Sales Rep, un ID Branch, un mese e un anno.
Ho bisogno di una query che restituirà la somma delle vendite di un rappresentante specifico per un anno, raggruppati per ramo e il mese, e la query deve restituire 0 se non v'è stata nessuna vendita in un ramo per quel mese. Ho il seguente, che non restituisce 0 se non ci sono le vendite:
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
Soluzione
Sarà necessario aggiungere i dati "mancanti" per essere in grado di farne parte.
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
Altri suggerimenti
È necessario fare un LEFT JOIN alle vendite, in modo da tornare anche i rappresentanti che non hanno tutti i record nella tabella vendite.
Se la query sta tornando NULL, è possibile utilizzare uno dei metodi coalescenza: COALESCE(SUM(...), 0)
restituirà il primo valore non NULL nella lista ...
È necessario utilizzare un join sinistro ed un IsNull per ottenere la somma giusta:
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
Hai ancora bisogno di fare un po 'più di lavoro con esso per ottenere i mesi mostrando anche se un venditore non ha le vendite in un determinato mese.
Ho cambiato il join da interno a sinistra esterno e aggiunto la funzione ISNULL per rami con nessuna vendita.
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