T-SQL, somme nulle pour aucune correspondance avec le rejoindre
-
11-09-2019 - |
Question
J'ai deux tables, une avec toutes mes branches, et une avec toutes mes ventes. Le tableau des ventes contient également un code représentant commercial, un ID de succursale, un mois et un an.
J'ai besoin d'une requête qui renverra la somme d'un chiffre d'affaires de rep spécifique pour une année, regroupés par branche et par mois, et la requête doit retourner 0 s'il n'y a pas eu de ventes dans une branche pour ce mois. J'ai ce qui suit, qui ne retourne pas 0 s'il n'y a pas de vente:
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
La solution
Vous devrez ajouter les données « manquantes » pour être en mesure de le joindre.
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
Autres conseils
Vous devez faire un LEFT JOIN aux ventes, de façon à revenir même les représentants qui n'ont pas de dossiers dans le tableau des ventes.
Si votre requête retourne NULL, vous pouvez utiliser l'une des méthodes coalescents: COALESCE(SUM(...), 0)
retourne la première valeur non NULL dans la liste ...
Vous devez utiliser une jointure gauche et un isnull pour obtenir le droit à la somme:
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
Vous avez encore besoin de faire un peu plus de travail avec elle pour obtenir les mois montrant aussi si un vendeur ne vend pas dans un mois donné.
J'ai changé la jointure de l'intérieur vers extérieur et ajouté a quitté la fonction ISNULL pour les branches sans ventes.
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