I have two tables that I need to join… I want to join table1 and table2 on ‘id’ – however in table two id is not unique. I only want one value returned for table two, and this value represents the sum of a column called ‘total_sold’ – within a specified date range (say one month), however I want more than one date range at the same time…
SELECT ta.id, sum(tb.total_sold) as total_sold_this_week, sum(tc.total_sold) as total_sold_this_month
FROM table_a as ta
LEFT JOIN table_b as tb ON ta.id=tb.id AND tb.date_sold BETWEEN ADDDATE(NOW(),INTERVAL -1 WEEK) AND NOW()
LEFT JOIN table_b as tc ON ta.id=tc.id AND tc.date_sold BETWEEN ADDDATE(NOW(),INTERVAL -1 MONTH) AND NOW()
GROUP BY ta.id
this works but does not SUM the rows – only returning one row for each id… how do I get the sum from table b instead of only one row???
Please criticise if format of question could use more work – I can rewrite and provide sample data if required – this is a trivialised version of a much larger problem.
-Thanks
Using Subqueries
One way to solve this would be to use subqueries.
LEFT JOINcreates a new "result" for each match in the right table, so using two LEFT JOINs is creating more ROWS than you want. You could just sub select the value you want, but this can be slow:Result:
Using SUM(CASE …)
This method doesn’t use subqueries (and will likely be faster on larger data sets). We want to join the table_a and table_b together once, using our "biggest" date range, and then use a
SUM()based on aCASEto calculate the "smaller range".This returns nearly the same resultset as the subquery example:
The only difference is the
0instead ofNULL. You could summarize as many date ranges as you’d like using this method, but its still probably best to limit the rows returned to the largest range in theONclause.Just to show how it works: removing the
GROUP BYandSUM()calls, and addingdate_soldto the SELECT returns this:Now when you
GROUP BY id, andSUM()the two total_sold columns you have your results!Old Advice
Before you brought the two different date ranges into the mix, you could use
GROUP BYto group using the table id on table1, and theSUM()aggregate function to add up the rows returned.The test data
NOW()is 2010-05-03