I have 4 tables as shown below
For each table I want the count of users that are present exclusively in that table (not present in other tables). The result should look something likes this
I have one way of getting desired result as shown below:
First Column:
SELECT COUNT(DISTINCT A.id) table1_only FROM table1 A LEFT JOIN (SELECT DISTINCT id FROM table2 UNION SELECT DISTINCT id FROM table3 UNION SELECT DISTINCT id FROM table4) B ON A.id = B.id WHERE B.id IS NULL
Second Column:
SELECT COUNT(DISTINCT A.id) table2_only FROM table2 A LEFT JOIN (SELECT DISTINCT id FROM table1 UNION SELECT DISTINCT id FROM table3 UNION SELECT DISTINCT id FROM table4) B ON A.id = B.id WHERE B.id IS NULL
Third Column:
SELECT COUNT(DISTINCT A.id) table3_only FROM table3 A LEFT JOIN (SELECT DISTINCT id FROM table1 UNION SELECT DISTINCT id FROM table2 UNION SELECT DISTINCT id FROM table4) B ON A.id = B.id WHERE B.id IS NULL
Fourth Column:
SELECT COUNT(DISTINCT A.id) table4_only FROM table4 A LEFT JOIN (SELECT DISTINCT id FROM table1 UNION SELECT DISTINCT id FROM table2 UNION SELECT DISTINCT id FROM table3) B ON A.id = B.id WHERE B.id IS NULL
But I wanted to know if there is any efficient and scalable way to get same result. Just for 4 tables the amount of code is too much.
Any ways of optimizing this task will be really helpful.
Sample fiddle. (This fiddle is for mysql, I am looking for a generic SQL based approach than any db specific approach)
P.S.: There is no complusion on the result needs to be in column wise. It can be row wise as well, as shown below:
Advertisement
Answer
I would approach this by combining the data from all tables. Then aggregate and filter:
select which, count(*) as num_in_table_only from (select id, min(which) as which, count(*) as cnt from ((select id, 1 as which from table1) union all (select id, 2 as which from table2) union all (select id, 3 as which from table3) union all (select id, 4 as which from table4) ) t group by id ) i where cnt = 1 group by which
Note: In your sample data, the id
s are unique in each table. This solution assumes that is true, but can easily be tweaked to handle duplicates within a table.