I have information on school athletics, with tables for school, season, cashflow, and cashflow_group. I'm trying to query for all schools with cashflow in one or more given cashflow_groups within a user-specified range. I need to query multiple different categories in the same query. I'm having trouble.
My query is below. The reason I did it this way is that I can sum multiple cashflow groups, and I thought it worked until I looked closely and saw that it sums the cashflow amount for all schools as total_cashflow_amount, when each school should have a different total, the sum of its associated cashflow rows.
SELECT distinct schools.*,
(SELECT sum(`cashflows`.amount) AS cf FROM `schools`
INNER JOIN `seasons` ON seasons.school_id = schools.id
INNER JOIN `cashflows` ON cashflows.season_id = seasons.id
INNER JOIN `cashflow_groups` ON `cashflow_groups`.id = `cashflows`.cashflow_group_id
WHERE ((`cashflow_groups`.id = 12) AND (`seasons`.`year` = 2010))) AS total_branding_cashflow
FROM `schools`
INNER JOIN `seasons` ON seasons.school_id = schools.id
INNER JOIN `cashflows` ON cashflows.season_id = seasons.id
INNER JOIN `cashflow_groups` ON `cashflow_groups`.id = `cashflows`.cashflow_group_id
INNER JOIN `seasons` seasons_schools ON seasons_schools.school_id = schools.id
WHERE (`seasons`.`year` = 2010)
GROUP BY schools.id
HAVING (total_branding_cashflow BETWEEN 50000000 AND 100000000)
ORDER BY schools.name ASC LIMIT 0, 50
In this query, total_branding_cashflow
is the total for all schools. I can't figure out how to get the total for each school individually in the subquery.
As it stands, I get a result like
| school.id | … | total_branding_cashflow |
| 2 | | 900000 |
| 5 | | 900000 |
when what I want is
| school.id | … | total_branding_cashflow |
| 2 | | 500000 |
| 5 | | 400000 |
Adding a GROUP BY to the subquery gives me the sum of each school's cashflow in a separate row, but subqueries only work when they give a single row, so this doesn't help me.
What am I missing? The reason I though to use subqueries is that I want to be able to look up multiple different cashflow_groups at the same time, like this:
SELECT distinct schools.*,
(SELECT sum(`cashflows`.amount) AS cf FROM `schools`
INNER JOIN `seasons` ON seasons.school_id = schools.id
INNER JOIN `cashflows` ON cashflows.season_id = seasons.id
INNER JOIN `cashflow_groups` ON `cashflow_groups`.id = `cashflows`.cashflow_group_id
WHERE ((`cashflow_groups`.id = 12) AND (`seasons`.`year` = 2010)) ) AS total_branding_cashflow,
(SELECT sum(`cashflows`.amount) AS cf FROM `schools`
INNER JOIN `seasons` ON seasons.school_id = schools.id
INNER JOIN `cashflows` ON cashflows.season_id = seasons.id
INNER JOIN `cashflow_groups` ON `cashflow_groups`.id = `cashflows`.cashflow_group_id
WHERE ((`cashflow_groups`.id = 1) AND (`seasons`.`year` = 2010)) ) AS total_ticket_sales_cashflow,
(SELECT sum(`cashflows`.amount) AS cf FROM `schools`
INNER JOIN `seasons` ON seasons.school_id = schools.id
INNER JOIN `cashflows` ON cashflows.season_id = seasons.id
INNER JOIN `cashflow_groups` ON `cashflow_groups`.id = `cashflows`.cashflow_group_id
WHERE ((`cashflow_groups`.id = 7) AND (`seasons`.`year` = 2010)) ) AS total_university_cashflow
FROM `schools`
INNER JOIN `seasons` ON seasons.school_id = schools.id
INNER JOIN `cashflows` ON cashflows.season_id = seasons.id
INNER JOIN `cashflow_groups` ON `cashflow_groups`.id = `cashflows`.cashflow_group_id
INNER JOIN `seasons` seasons_schools ON seasons_schools.school_id = schools.id
WHERE (`seasons`.`year` = 2010)
GROUP BY schools.id
HAVING (total_branding_cashflow BETWEEN 50000000 AND 100000000) AND
(total_ticket_sales_cashflow BETWEEN 50000000 AND 100000000) AND
(total_university_cashflow BETWEEN 0 AND 10000000)
ORDER BY schools.name ASC LIMIT 0, 50
I didn't think I could do this with a SUM that isn't in its own subquery. I'm working on a rails app, and could probably come up with a way to do this via ruby code. But that doesn't seem right and I'd prefer to get it down in SQL if possible. Thanks!
Some suggestions:
seasons
once. A join causes rows from the left table to be duplicated, so they can be summed twice by thesum
aggregate. When in doubt, run the query withoutgroup by
for an example school.inner_schools.id = outer_schools.id
For example:
For multiple categories, you could use a case: