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.