Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MySQL Double count on left join

Database Structure

CREATE TABLE installs(
    id INT, PRIMARY KEY(id), 
    created DATETIME)

CREATE TABLE uninstalls(
    id INT, PRIMARY KEY(id),
    created DATETIME,
    install_id INT)

The Query ("Me vs. The MySQL")

SELECT DATE(installs.created),
  COUNT(installs.id),
  COUNT(uninstall.id)
FROM installs
LEFT JOIN uninstalls ON uninstalls.install_id = installs.id
GROUP BY DATE(installs.created)

The "Expected" Output

DATE(installs.created) | COUNT(installs.id) | COUNT(uninstalls.id) 
  2012-11-20           | *installs on date* | *uninstalls on date*

So - I am looking a row per day, with the number of installs/uninstalls that happened on that day.

The Problem

The data for the 'installs' is correct for each day. BUT the data for the 'uninstalls' for each day is sadly incorrect.

like image 988
Hzmy Avatar asked Nov 21 '12 17:11

Hzmy


People also ask

Can LEFT join increase row count?

Left joins can increase the number of rows in the left table if there are multiple matches in the right table.

WHAT IF LEFT join has multiple matches?

LEFT JOINs can return multiple matches on a single key value, depending on your requirements this may or may not be desirable. In Oracle, you can use the analytical function ROW_NUMBER to choose a single value when multiple matches on a key occur.

Can you use LEFT join twice?

Yes, indeed! You can use multiple LEFT JOINs in one query if needed for your analysis.

How do I join two tables and counts in SQL?

To achieve this for multiple tables, use the UNION ALL. select sum(variableName. aliasName) from ( select count(*) as yourAliasName from yourTableName1 UNION ALL select count(*) as yourAliasName from yourTableName2 ) yourVariableName; Let us implement the above syntax.


1 Answers

Count the installs and the uninstall separately, adding a column (of zeroes) for the other count to each of them. Then combine the two with UNION, group by date once again and take the max for each date (to eliminate the added zeroes):

SELECT created as date, max(installs) as installs, max(uninstalls) as uninstalls
FROM
  (SELECT created, count(*) AS installs, 0 AS uninstalls
   FROM installs
   GROUP BY created
  UNION ALL
   SELECT created, 0 AS installs, count(*) AS uninstalls
   FROM uninstalls
   GROUP BY created) c
GROUP BY created
ORDER BY created
like image 133
Terje D. Avatar answered Oct 02 '22 19:10

Terje D.