Shnibble
Shnibble

Reputation: 110

Calculating SUM() results from subqueries into a total

My brain is starting to hurt with this query and I would appreciate some guidance. What I am trying to get as the result of this query are three values: attendanceScore, lootScore, and totalScore (attendanceScore - lootScore).


After some work I have come up with a working query to get attendanceScore and lootScore:

SELECT 
(SELECT SUM(t3.`value`)
FROM `attendance` t1
    INNER JOIN `attendancelog` t2
        ON t2.`id` = t1.`attendancelog_id`
    INNER JOIN `attendancevalues` t3
        ON t3.`eventtype_id` = t2.`type` AND t3.`attendancetype_id` = t1.`type`
WHERE t1.`user_id` = 3) as attendanceScore,

(SELECT SUM(t2.`cost`) 
    FROM `loot` t1
        INNER JOIN `loottypes` t2
            ON t2.`id` = t1.`type`
    WHERE t1.`user_id` = 3) as lootScore

I know this doesn't work, but I tried to add (attendanceScore - lootScore) to the query but it says those fields are not available. That is ultimately what I need to complete the query.

I can get the result I want by copying each of the subqueries directly into (attendanceScore - lootScore) but it is just absolutely hideous and I'm sure unnecessary:

SELECT 
(SELECT SUM(t3.`value`)
FROM `attendance` t1
    INNER JOIN `attendancelog` t2
        ON t2.`id` = t1.`attendancelog_id`
    INNER JOIN `attendancevalues` t3
        ON t3.`eventtype_id` = t2.`type` AND t3.`attendancetype_id` = t1.`type`
WHERE t1.`user_id` = 3) as attendanceScore,

(SELECT SUM(t2.`cost`) 
    FROM `loot` t1
        INNER JOIN `loottypes` t2
            ON t2.`id` = t1.`type`
    WHERE t1.`user_id` = 3) as lootScore,

(
    (SELECT SUM(t3.`value`)
    FROM `attendance` t1
        INNER JOIN `attendancelog` t2
            ON t2.`id` = t1.`attendancelog_id`
        INNER JOIN `attendancevalues` t3
            ON t3.`eventtype_id` = t2.`type` AND t3.`attendancetype_id` = t1.`type`
    WHERE t1.`user_id` = 3) - (SELECT SUM(t2.`cost`) 
    FROM `loot` t1
        INNER JOIN `loottypes` t2
            ON t2.`id` = t1.`type`
    WHERE t1.`user_id` = 3)
) as totalScore

Could someone help me understand what methods to use for cleaning this up into something more streamlined and efficient?

Upvotes: 0

Views: 37

Answers (1)

Radim Bača
Radim Bača

Reputation: 10701

You may use an inline view

SELECT attendanceScore,
        lootScore,
        attendanceScore - lootScore as totalScore
FROM
(
    SELECT 
    (
        SELECT SUM(t3.`value`)
        FROM `attendance` t1
        INNER JOIN `attendancelog` t2
            ON t2.`id` = t1.`attendancelog_id`
        INNER JOIN `attendancevalues` t3
            ON t3.`eventtype_id` = t2.`type` AND t3.`attendancetype_id` = t1.`type`
        WHERE t1.`user_id` = 3
    ) as attendanceScore,
    (
        SELECT SUM(t2.`cost`) 
        FROM `loot` t1
        INNER JOIN `loottypes` t2 ON t2.`id` = t1.`type`
        WHERE t1.`user_id` = 3) as lootScore
) t

Upvotes: 1

Related Questions