sql >> Databasteknik >  >> RDS >> Sqlserver

Aggregera funktioner på flera tabeller ger inte korrekta resultat

När du lägger till ytterligare en tabell kan du påverka antalet rader och när det händer kommer aggregationer också att påverkas. För att undvika detta aggregerar detaljtabellen så att det bara kan finnas en rad per beställning, då kommer de andra aggregeringarna att förbli konsekventa.

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

REDIGERA

Använd inte "23:59" som slutpunkt för ett datumintervall, som inte är korrekt och kan leda till felaktiga resultat. Det finns ett väldigt enkelt och mer exakt alternativ som bara kräver att du slutar använda "mellan". Dessutom är '12/31/2015 23:59' INTE ett säkert sätt att ange ett datum/tidsvärde. Använd "20160101" som ÄR det säkraste bokstavliga formatet i 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. Motsvarar strftid i Postgres

  2. Hur skickar man godtyckliga parametrar till Oracle trigger?

  3. Skillnaden mellan FIELD() och FIND_IN_SET() i MySQL

  4. SQLite byter namn på PRINTF() till FORMAT()