简体   繁体   中英

Sum of sums from tables of line items SQL Subquery

I have 3 tables: CUSTOMERS CLOSEDORDERS CLOSEDORDERARCHIVES

Each is linked by a customer ID field. CLOSEDORDERS and CLOSEDORDERSARCHIVES are tables with every line item of every invoice ever sold. I'm trying to come up with lifetime totals for the customers, but I'm stuck on the final sum. Here is what I have written, it outputs correct totals for each table in two columns (some of the values are null):

SELECT CUSTOMERS.Company, CUSTOMERS.[Ship City], CUSTOMERS.[Ship State], 
      (SELECT SUM (CLOSEDORDERSARCHIVE.Quantity*CLOSEDORDERSARCHIVE.SellPrice) 
      FROM CLOSEDORDERSARCHIVE 
      WHERE CLOSEDORDERSARCHIVE.CustomerID = CUSTOMERS.ID) AS archiveTotal, 
            (SELECT SUM (CLOSEDORDERS.Quantity*CLOSEDORDERS.SellPrice)
            FROM CLOSEDORDERS
            WHERE CLOSEDORDERS.CustomerID = CUSTOMERS.ID) AS currentTotal
FROM CUSTOMERS, CLOSEDORDERSARCHIVE, CLOSEDORDERS
WHERE (((CUSTOMERS.Branch)=33));

When I search, I find this answer that seems similar, but I can't make it work, is it because the sums are summed from line items in the tables and grouped by customer? Also, this is one of my first queries, is there a more efficient way to write/accomplish this?

Sum of sums in different tables

We can break this into a simpler problem first: Put everything you need in one table.

If the only columns required for the sum are the quantities and sellprices (and the ID of course) you can union them in a subquery and calculate the total of that later. The subquery will look something like:

select CustomerID as 'ID', Quantity as 'Quantity', SellPrice as 'SellPrice'
from CLOSEDORDERSARCHIVE

UNION ALL

select CustomerID as 'ID', Quantity as 'Quantity', SellPrice as 'SellPrice'
from CLOSEDORDERS

After that, you can select from that subquery and group by customer ID and you'll get the sum totals for each customer:

select ID, SUM(Quantity*SellPrice) from(

select CustomerID as 'ID', Quantity as 'Quantity', SellPrice as 'SellPrice'
from CLOSEDORDERSARCHIVE

UNION ALL

select CustomerID as 'ID', Quantity as 'Quantity', SellPrice as 'SellPrice'
from CLOSEDORDERS
) as subq1
GROUP By ID

And I think that's what you need. You can even join the last query with the table Customers if you want the customer name and stuff like that to appear =)

I think least unintuitive solution is to join on subqueries (ugh!). Here's an (oversimplified, see caveat below) example:

SELECT
  c.Company,
  c.[Ship City],
  c.[Ship State],
  co.Total + coa.Total AS 'Grand Total'
FROM CUSTOMERS c
LEFT OUTER JOIN (
  SELECT CustomerID, SUM(Quantity*SellPrice) as 'Total'
  FROM CLOSEDORDERS
  GROUP BY CustomerID
) AS 'co' ON c.ID = co.CustomerID
LEFT OUTER JOIN (
  SELECT CustomerID, SUM(Quantity*SellPrice) as 'Total'
  FROM CLOSEDORDERSARCHIVE
  GROUP BY CustomerID
) AS 'coa' ON c.ID = coa.CustomerID
WHERE c.Branch = 33

In this case, we're creating two intermediate tables (co and coa) which hold CLOSEDORDERS's and CLOSEDORDERSARCHIVE's order totals for each customer listed in the table.

Caveat: if there are no orders in CLOSEDORDERS or CLOSEDORDERSARCHIVE for a company, than co.Total (or coa.Total) will be NULL for that company. You need to check for this or the addition will be wrong (IIRC NULL + a number = NULL). So the "co.Total" and "coa.Total" expressions of the SELECT clause should use a COALESCE or CASE statement to check for it. Something like:

...COALESCE(co.Total,0) + COALESCE(coa.Total,0) AS 'Grand Total'...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM