Reputation: 915
I have three tables: wi_district, wi_group, and wi_training. I need to count groups and trainings based on districts. For this purpose I have used following SQL;
SELECT wi_district.dst_name, COUNT(grp_id) AS group_count, MAX(grp_created_date) as grp_created_date FROM wi_group INNER JOIN wi_district ON wi_district.dst_id=wi_group.grp_dst_id AND wi_group.grp_deleted=0 AND wi_group.grp_type IN (3) GROUP BY wi_district.dst_name
The query counts group for each district. Likewise,
SELECT wi_district.dst_name, COUNT(trn_id) AS training_count, MAX(trn_created_date) as trn_created_date FROM wi_training INNER JOIN wi_district ON wi_district.dst_id=wi_training.dst_id AND wi_training.trn_deleted=0 AND wi_training.trn_beneficiary_type IN (-1,2,8,9,10) GROUP BY wi_district.dst_name
The query counts training for each district. Now I need to combine all the results obtained from SQL1 and SQL2 and get the result in the form of
dst_name || group_count || grp_created_date || training_count || trn_created_date
The problem is whenever I used SQL1 LEFT JOIN SQL2 then it displayed the result respective to SQL1 where the result of SQL2 can't be obtained and vice-versa. Please help me sort out with this problem in MySQL
Upvotes: 1
Views: 134
Reputation: 1258
You need to DRIVE it from the grouping table. Like so.
SELECT D.dst_name, COUNT(grp_id) AS group_count, MAX(grp_created_date) as grp_created_date, COUNT(trn_id) AS training_count, MAX(trn_created_date) as trn_created_date
FROM wi_district D
LEFT JOIN wi_group G ON D.dst_id = G.grp_dst_id AND G.grp_deleted=0 AND G.grp_type IN (3)
LEFT JOIN wi_training T ON D.dst_id = T.dst_id AND T.trn_deleted=0 AND T.trn_beneficiary_type IN (-1,2,8,9,10)
GROUP BY wi_district.dst_name
And if you only want rows if they exist on either table, add a clause:
WHERE NOT G.grp_dst_id IS NULL OR NOT D.dst_id IS NULL
Upvotes: 0
Reputation: 2711
Why use names like dst_name? It is better to write out the full name, so you will also understand what it means after a few months.
Anyway, this query should do the trick
select d.dst_name as district
, count(distinct g.grp_id) as group_count
, max(grp_created_date) as group_created_date
, count(distinct trn_id) as training_count
, max(trn_created_date) as trn_created_date
from wi_district d
left join wi_group g on d.dst_id = g.grp_dst_id
and g.grp_deleted = 0
and g.grp_type in (3)
left join wi_training t on d.dst_id = t.dst_id
and t.trn_deleted = 0
and t.trn_beneficiary_type IN (-1,2,8,9,10)
group by d.dst_name
Upvotes: 0
Reputation: 4191
I think you can join the filtered tables and then group by the district name. Like so:
SELECT dist.dst_name AS dst_name,
COUNT(grp.grp_id) AS group_count, MAX(grp.grp_created_date) AS grp_created_date,
COUNT(trn.trn_id) AS training_count, MAX(trn.trn_created_date) AS trn_created_date
FROM wi_district AS dist
LEFT JOIN (
SELECT dst_id, trn_id, trn_created_date
FROM wi_training
WHERE trn_deleted=0
AND trn_beneficiary_type IN (-1,2,8,9,10)
) AS trn ON trn.dst_id=dist.dst_id
LEFT JOIN (
SELECT grp_dst_id, grp_id, grp_created_date
FROM wi_group
WHERE grp_deleted=0
AND grp_type IN (3)
) AS grp ON grp.grp_dst_id = dist.dst_id
GROUP BY dist.dst_name
Upvotes: 0