Lorsque vous ajoutez une autre table, vous pouvez affecter le nombre de lignes et lorsque cela se produit, les agrégations seront également affectées. Pour éviter cela, agrégez le tableau de détail afin qu'il ne puisse y avoir qu'une seule ligne par commande, les autres agrégations resteront cohérentes.
SELECT
Customers.EmailAddress
, COUNT(Orders.OrderID) AS 'overall NumOrders'
, SUM(Orders.PaymentAmount) AS 'overall TotalOrdered'
, SUM(od.totalcost) AS totalcost
, COUNT(CASE WHEN Orders.OrderDate >= '20170101' THEN Orders.OrderID END) AS '2017 NumOrders'
, SUM(CASE WHEN Orders.OrderDate >= '20170101' THEN Orders.PaymentAmount END) AS '2017 TotalOrdered'
, COUNT(CASE WHEN Orders.OrderDate BETWEEN ' 01/01/2015 00:00' AND '12/31/2015 23:59' THEN Orders.OrderID END) AS '2015 NumOrders'
, SUM(CASE WHEN Orders.OrderDate BETWEEN ' 01/01/2015 00:00' AND '12/31/2015 23:59' THEN Orders.PaymentAmount END) AS '2015 TotalOrdered'
FROM Customers
JOIN Orders ON Customers.Customerid = Orders.Customerid
JOIN (
SELECT
Orderid
, SUM((Vendor_Price) * (Quantity)) AS totalcost
FROM OrderDetails
GROUP BY
Orderid
) od ON Orders.Orderid = od.Orderid
WHERE Orders.OrderStatus NOT IN ('Cancelled', 'Payment Declined')
AND Orders.OrderDate BETWEEN ' 01/01/2015 00:00' AND GETDATE()
GROUP BY
Customers.EmailAddress
MODIFIER
Veuillez ne pas utiliser "23:59" comme point final pour une plage de dates, ce n'est pas exact et peut conduire à des résultats incorrects. Il existe une alternative très simple et plus précise qui vous demande simplement d'arrêter d'utiliser "entre". De plus, '12/31/2015 23:59' n'est PAS un moyen sûr de spécifier une valeur de date/heure. Utilisez '20160101' qui EST le format littéral le plus sûr dans SQL Server YYYYMMDD
.
, COUNT(CASE WHEN Orders.OrderDate >= '20150101' AND Orders.OrderDate < '20160101' THEN Orders.OrderID END) AS '2015 NumOrders'
, SUM(CASE WHEN Orders.OrderDate >='20150101' AND Orders.OrderDate < '20160101' THEN Orders.PaymentAmount END) AS '2015 TotalOrdered'