sql >> Database >  >> RDS >> Sqlserver

Geaggregeerde functies op meerdere tabellen geven niet de juiste resultaten

Wanneer u een andere tabel toevoegt, kunt u het aantal rijen beïnvloeden en wanneer dat gebeurt, worden de aggregaties ook beïnvloed. Om dit te voorkomen, aggregeert u de detailtabel zodat er slechts één rij per bestelling kan zijn, zodat de andere aggregaties consistent blijven.

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

BEWERKEN

Gebruik a.u.b. geen "23:59" als eindpunt voor een datumbereik, dat niet nauwkeurig is en tot onjuiste resultaten kan leiden. Er is een heel eenvoudig en nauwkeuriger alternatief waarvoor u alleen maar hoeft te stoppen met het gebruik van "tussen". Bovendien is '31-12-2015 23:59' NIET een veilige manier om een ​​datum/tijd-waarde op te geven. Gebruik '20160101' wat IS . is het veiligste letterlijke formaat in 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'



  1. PreparedStatement is null in Where-clausule zonder if voorwaardelijke (dynamische query) of wartaalwaarden

  2. ETL vs ELT:wij stellen, u oordeelt

  3. Aangepaste tijdzone instellen in Django/PostgreSQL (Indian Standard Time)

  4. Ik wil dat mysql-tabel twee talen ondersteunt