Davide Sousa
Davide Sousa

Reputation: 107

SQL Sum of Sums

I have calculated the sum of a count in different tables. This is done twice, once for each performanceID. Now I want to get the sum of the two sums.

Below is the code for the two sums that I do at the moment:

    SELECT SUM((COUNT (BookingID) * CategoryPrice)) AS TotalAmount
    FROM Booking, Production
    WHERE Booking.PerformanceID IN(SELECT PerformanceID FROM Performance WHERE PerformanceID = '1')
    and Production.ProductionID IN 
    (SELECT ProductionID FROM Performance WHERE PerformanceID = '1') 
    GROUP BY BookingID, CategoryPrice
    UNION ALL
    SELECT SUM((COUNT (BookingID) * CategoryPrice)) AS TotalAmount
    FROM Booking, Production
    WHERE Booking.PerformanceID IN(SELECT PerformanceID FROM Performance WHERE PerformanceID = '2')
    and Production.ProductionID IN 
    (SELECT ProductionID FROM Performance WHERE PerformanceID = '2')
     GROUP BY BookingID, CategoryPrice

The results I get are:

TOTALAMOUNT
-----------
         70
         60 

How do I sum up the two sums here?

Upvotes: 3

Views: 12131

Answers (2)

Ben
Ben

Reputation: 52863

I'm never going to compete with the FGITW but I have to say something about this query...

If we add whitespace I hope you'll see what I mean:

SELECT SUM( (COUNT(BookingID) * CategoryPrice) ) AS TotalAmount
  FROM Booking
     , Production
 WHERE Booking.PerformanceID IN ( SELECT PerformanceID 
                                   FROM Performance 
                                  WHERE PerformanceID = '1')
   AND Production.ProductionID IN ( SELECT ProductionID FROM Performance 
                                     WHERE PerformanceID = '1') 
 GROUP BY BookingID, CategoryPrice
 UNION ALL
SELECT SUM( (COUNT(BookingID) * CategoryPrice)) AS TotalAmount
  FROM Booking
     , Production
 WHERE Booking.PerformanceID IN ( SELECT PerformanceID 
                                    FROM Performance 
                                   WHERE PerformanceID = '2')
   AND Production.ProductionID IN ( SELECT ProductionID 
                                      FROM Performance 
                                     WHERE PerformanceID = '2')
 GROUP BY BookingID, CategoryPrice

Breaking the query down the only reason that you got two rows returned were the analytic functions and the union all.

  1. You're doing a cartesian join between booking and production, this means that you multiply the number of rows in each by each other.
  2. Your sub-selects on performance are returning one value, which is already known. There's no reason to do them at all.
  3. You're implicitly converting numbers into strings and back into numbers again.
  4. You're scanning a table or index 8 times here!

It appears as though you want the total amount taken for each performance in which case your query can be simplified to the following:

SELECT SUM(bookings * CategoryPrice)
  FROM ( SELECT CategoryPrice , count(*) as bookings
           FROM Booking b
           JOIN performance per
             ON p.performanceid =  per.performanceid
           JOIN Production p
             ON p.productionid = per.productionid
          WHERE p.performanceid in (1, 2)
          GROUP BY CategoryPrice
                )

Please note the explicit join syntax, this has been around for a few decades, makes things a lot clearer and helps stop mistakes. This query will do two range scans, one of booking and one of production, assuming you have indexes on performanceid on both tables. It'll also do a unique scan of performance assuming that performanceid is the primary key of this table.

As an explanation of what this does, now I've finally managed to get your schema correct! We select the two performances, 1 and 2. We then select every production related to those performances and every booking related to those productions. You may be able to simplify this further depending on what table categoryprice is in. We then get the number of bookings per categoryprice and sum the product of these to give you the total value.

As a bit of advice, I would always recommend understanding what values you expect to be returned from a query before you accept that your query is correct. The very best can and do make mistakes. Being able to catch them because you can see that the returned values are incorrect will help.

Further Reading:

Upvotes: 7

hkutluay
hkutluay

Reputation: 6944

Use sub sql, and sum TotalAmount

SELECT SUM(TotalAmount)
   ( SELECT SUM((COUNT (BookingID) * CategoryPrice)) AS TotalAmount
        FROM Booking, Production
        WHERE Booking.PerformanceID IN(SELECT PerformanceID FROM Performance WHERE PerformanceID = '1')
        and Production.ProductionID IN 
        (SELECT ProductionID FROM Performance WHERE PerformanceID = '1') 
        GROUP BY BookingID, CategoryPrice
        UNION ALL
        SELECT SUM((COUNT (BookingID) * CategoryPrice)) AS TotalAmount
        FROM Booking, Production
        WHERE Booking.PerformanceID IN(SELECT PerformanceID FROM Performance WHERE PerformanceID = '2')
        and Production.ProductionID IN 
        (SELECT ProductionID FROM Performance WHERE PerformanceID = '2')
Group By CategoryPrice)

Upvotes: 0

Related Questions