Get table row count using multiple table join - mysql

I have Three tables company_m , client_m , companyuser_m
company_m
CompanyID CompName
----------+-----------
7 Comp3
8 Comp2
9 Comp1
10 Company
11 Company4
client_m
clid AttachToCompanyID clname
-----+--------------------+------
1 7 client1
2 7 client2
6 8 client3
companyuser_m
uid CompanyID uname
---+---------+-------
1 7 user1
2 10 user2
My Goal
I need to get the count of all clients and users of the corresponding company
Expected Output
CompanyID CompName clientcount usercount
---------+-----------+--------------+--------
7 Comp3 2 1
8 Comp2 1 0
9 Comp1 0 0
10 Company 3 0 1
11 Company4 0 0
My Code
select company_m.CompanyID,company_m.CompName,
count(client_m.AttachToCompanyID) as clientcount ,
count(companyuser_m.CompanyID) as usercount from company_m
left join client_m on client_m.AttachToCompanyID=company_m.CompanyID
left join companyuser_m on companyuser_m.CompanyID=company_m.CompanyID
group by company_m.CompanyID
But the above code not gives the correct output.
check my fiddle

You should be left joining to separate subqueries which find the counts in the respective client_m and companyuser_m tables:
SELECT
t1.CompanyID,
t1.CompName,
COALESCE(t2.cnt, 0) AS client_count,
COALESCE(t3.cnt, 0) AS user_count
FROM company_m t1
LEFT JOIN
(
SELECT AttachToCompanyID, COUNT(*) AS cnt
FROM client_m
GROUP BY AttachToCompanyID
) t2
ON t1.CompanyID = t2.AttachToCompanyID
LEFT JOIN
(
SELECT CompanyID, COUNT(*) AS cnt
FROM companyuser_m
GROUP BY CompanyID
) t3
ON t1.CompanyID = t3.CompanyID;

Related

Select all Groups and check if User is in a Group or not

I have two tables groups and groups_members
groups
id
name
1
GROUP 1
2
GROUP 2
3
GROUP 2
groups_members
group_id
user_id
1
123
2
123
2
555
1
4643
3
45434
Now I want to display ALL groups and check if the user i show the groups for (lets say user_id = 555) is in a group or not. Something like this:
SELECT g.id, g.name, is_in_group
FROM g.groups
JOIN groups_members gm ON gm.user_id = 555
Expected output:
id
name
is_in_group
1
GROUP 1
NULL
2
GROUP 2
1
3
GROUP 3
NULL
You have several ways to do so, a simple trick that comes to my mind is this one:
SELECT
g.*,
CAST(gm.user_id / gm.user_id AS UNSIGNED) AS is_in_group
FROM sgroups AS g
LEFT JOIN sgroups_members AS gm
ON g.id = gm.group_id
AND gm.user_id = 555;
-- id name is_in_group
-- 1 GROUP 1 NULL
-- 2 GROUP 2 1
-- 3 GROUP 3 NULL

mysql count on multiple columns from another table

I would like to get count of two columns from another table. For example, the source data is as below for the table called employee_master
emp_code dept_id sub_dept_id
1 10 22
2 11 20
3 10 22
4 10 22
5 11 20
6 10 21
Another source table called punching_data_table as shown below which is being joined with employee_master.
emp_code present
1 10:01 AM
2 10:02 AM
3 10:02 AM
4 10:03 AM
5 10:11 AM
6 10:09 AM //biometric punching time shown
The result is suppose to look like below.
dept_id dept_count sub_dept_id sub_dept_count
10 4 22 3
10 4 21 1
11 2 20 2
Tried with following code but it doesn't count seperately for both columns even though applied group by employee_master.dept_id, employee_master.sub_dept_id. Please note that there is only 1 column common between both table that is emp_code.
SELECT p.emp_code
, e.emp_code
, COUNT(e.dept_id) dept_id_count
, COUNT(e.sub_dept_id) sub_dept_id_count
FROM punching_data_table p
LEFT
JOIN employee_master e
ON e.emp_code = p.emp_code
GROUP
BY e.dept_id
, e.sub_dept_id
Any help on the subject with explanation will be highly appreciated.
This query (SQLFiddle) will give you the output that you specify:
SELECT em1.dept_id, em2.dept_count, em1.sub_dept_id, COUNT(em1.sub_dept_id) AS sub_dept_count
FROM employee_master em1
JOIN (SELECT dept_id, COUNT(dept_id) as dept_count
FROM employee_master e
JOIN punching_data_table p
ON e.emp_code = p.emp_code
GROUP BY dept_id) em2
ON em1.dept_id = em2.dept_id
WHERE EXISTS (SELECT * FROM punching_data_table pdt WHERE pdt.emp_code = em1.emp_code)
GROUP BY dept_id, sub_dept_id
Output:
dept_id dept_count sub_dept_id sub_dept_count
10 4 21 1
10 4 22 3
11 2 20 2
If you have a department names table e.g.
CREATE TABLE dept_master (dept_id INT, dept_name VARCHAR(20));
INSERT INTO dept_master VALUES
(10, 'Department 10'),
(11, 'Department 11');
You can join that as well using this query (SQLFiddle):
SELECT d.dept_name, em2.dept_count, em1.sub_dept_id, COUNT(em1.sub_dept_id) AS sub_dept_count
FROM employee_master em1
JOIN (SELECT dept_id, COUNT(dept_id) as dept_count
FROM employee_master e
JOIN punching_data_table p
ON e.emp_code = p.emp_code
GROUP BY dept_id) em2
ON em1.dept_id = em2.dept_id
JOIN dept_master d on d.dept_id = em1.dept_id
WHERE EXISTS (SELECT * FROM punching_data_table pdt WHERE pdt.emp_code = em1.emp_code)
GROUP BY d.dept_id, sub_dept_id
And then get department names in the output instead of ids:
dept_name dept_count sub_dept_id sub_dept_count
Department 10 4 21 1
Department 10 4 22 3
Department 11 2 20 2
Try this query
SELECT emp_code, MAX(dept_id_count) as dept_id_count, MAX(sub_dept_id_count) as sub_dept_id_count
FROM
(SELECT p.emp_code , COUNT(e.dept_id) dept_id_count, 0 as sub_dept_id_count
FROM punching_data_table p
LEFT JOIN employee_master e ON e.emp_code = p.emp_code
GROUP BY e.dept_id
UNION
SELECT p.emp_code, 0 as dept_id_count, COUNT(e.sub_dept_id) sub_dept_id_count
FROM punching_data_table p
LEFT JOIN employee_master e ON e.emp_code = p.emp_code
GROUP BY e.sub_dept_id) as subQuery
GROUP BY emp_code
There are some things which are not clear in your question for example do you want distinct employees or just a occurrences of employees, what happens if an employee does not exist in punching_data. I have made some assumptions in this answer but the crux of it is that you create 2 sub queries and join them on dept id which will force a 1 to many join
so given
drop table if exists employee_master,punching_data_table;
create table employee_master
(emp_code int, dept_id int, sub_dept_id int);
insert into employee_master values
(1 , 10 , 22),
(2 , 11 , 20),
(3 , 10 , 22),
(4 , 10 , 22),
(5 , 11 , 20),
(6 , 10 , 21 ),
(7 , 10 , 21);
create table punching_data_table(emp_code int);
insert into punching_data_table values
(1),
(2),
(3),
(4) ,
(5),
(6);
select a.dept_id,a.empcodes,s.sub_dept_id,s.empcodes from
(
select dept_id ,count(distinct emp_code) empcodes
from employee_master
where emp_code in (select emp_code from punching_data_table)
group by dept_id
) a
join
(select dept_id , sub_dept_id, count(distinct emp_code) empcodes
from employee_master
where emp_code in (select emp_code from punching_data_table)
group by dept_id,sub_dept_id) s
on s.dept_id = a.dept_id
order by a.dept_id,s.sub_dept_id
Result
+---------+----------+-------------+----------+
| dept_id | empcodes | sub_dept_id | empcodes |
+---------+----------+-------------+----------+
| 10 | 4 | 21 | 1 |
| 10 | 4 | 22 | 3 |
| 11 | 2 | 20 | 2 |
+---------+----------+-------------+----------+
3 rows in set (0.00 sec)
This result can be achieved without punching_data_table
SELECT t1.dept_id,
t2.sub_dept_id,
t1.count_dept,
t2.count_sub
FROM (SELECT dept_id,
sub_dept_id,
Count(dept_id) AS count_dept
FROM employee_master
GROUP BY dept_id)t1
LEFT JOIN (SELECT sub_dept_id,
dept_id,
Count(sub_dept_id) AS count_sub
FROM employee_master
GROUP BY sub_dept_id)t2
ON t1.dept_id = t2.dept_id

How to get sum of amount from multiple accounts which return by join

I have 3 tables like:
owner_details:-
owner_id owner_name
---------------------
1 A
2 B
3 C
-------------------
vehicle_owner:-
v_id vehicle_id owner_id
-------------------------
1 1 1
2 2 2
3 4 1
4 3 1
5 5 3
transaction:-
id v_id amount transaction_type
--------------------------------
1 1 100 0
2 2 250 1
3 1 150 1
4 3 450 1
5 1 200 0
6 4 300 1
7 5 150 0
8 5 200 1
transaction_type= 0 then (-) transaction_type=1 then (+)
Owner A (1) have 3 vehicles with v_id (1,3,4) in table vehicle_owner.
v_id (1,3,4) have 5 entries in table transaction (1,3,4,5,6) with sum of amount 600 (-100+150+450-200+300)
Now I want listing like this:-.
owner_id owner_name amount
---------------------
1 A 600
2 B 250
3 C 50
-------------------
You can use the following query:
SELECT od.owner_id, od.owner_name, SUM(t.amount) AS amount
FROM owner_details od INNER JOIN vehicle_owner vo ON od.owner_id = vo.owner_id
INNER JOIN `transaction` t ON vo.v_id = t.v_id
GROUP BY od.owner_id
If you want to use the additional transaction_type you can use the following:
SELECT od.owner_id, od.owner_name, SUM(CASE WHEN t.transaction_type = 0 THEN t.amount * -1 ELSE t.amount END) AS amount
FROM owner_details od INNER JOIN vehicle_owner vo ON od.owner_id = vo.owner_id
INNER JOIN `transaction` t ON vo.v_id = t.v_id
GROUP BY od.owner_id
demo: http://sqlfiddle.com/#!9/c5f8d/1/1
Try this:
SELECT A.owner_id, A.owner_name, SUM(IFNULL(amount,0)) AMOUNT
FROM owner_details A LEFT JOIN
vehicle_owner B
ON A.owner_id=B.owner_id
LEFT JOIN `transaction` C
ON C.v_id=B.v_id
GROUP BY A.owner_id, A.owner_name;
It works for me
SELECT od.owner_id,
od.owner_name,
Sum(t.amount) AS amount
FROM owner_details od
INNER JOIN vehicle_owner vo
ON od.owner_id = vo.owner_id
INNER JOIN (SELECT v_id,
Coalesce(Sum(CASE
WHEN type = 0 THEN -amount
ELSE +amount
end), 0.0) AS amount
FROM `transaction`
GROUP BY v_id) t
ON vo.v_id = t.v_id
GROUP BY od.owner_id
Thanks Sebastian Brosch for quick response !!!

sql group by although there is not value

I have a table where exists 4 entries like this.
class_type
id type
1 A
2 B
3 M
4 T
and another table where these values are foreign key.
id number id_class_type
1 10 1
2 11 1
3 12 2
4 13 1
5 14 2
6 15 3
7 16 1
8 17 3
So what i want is count(*) and group by id_class_type but with all class_type (1,2,3,4) although there is not present the id 4.
if you want only the class tha match you can use inner join
select a.class_type, count(*)
from class_type a
inner join table2 b on a.id = b.id_class_type
group by a.class_type
otherwise you can use left join
select a.class_type, count(*)
from class_type a
left join table2 b on a.id = b.id_class_type
group by a.class_type

Mysql group_concat for count in sub query using parent filed is not allowed

I need to process album count for each of the country per artist; however, I have a problem once I do group_concat for count in mysql, I search a bit in stackoverflow, I found I have to do sub select for group_concat. The problem is once I do the sub select in from I can not use a.id from the parent from filed table. I got error like following Unknown column 'a.id' in 'where clause'
This is the query:
SELECT a.seq_id, a.id
(SELECT GROUP_CONCAT(cnt) AS cnt FROM (
SELECT CONCAT_WS('-', mgr.country_code, count(mgr.media_id)) AS cnt
FROM music_album_artists AS ma
JOIN media_geo_restrict AS mgr ON ma.album_id = mgr.media_id
WHERE ma.artist_id = a.id
GROUP BY mgr.country_code
) count_table
) AS album_count
FROM music_artist AS a
WHERE a.seq_id > 0 and a.seq_id < 10000
The sample data in tables:
music_artists:
seq_id id name
1 1 Hola
2 2 Vivi
music_album_artists:
id artist_id album_id
1 1 1
2 1 2
3 1 5
4 1 10
5 2 2
6 2 10
6 2 1
media_geo_restrict:
album_id country_code
1 BE
1 CA
1 DE
1 US
2 CH
2 CA
2 CH
5 DE
10 US
The result I would like to have
seq_id id album_count
1 1 BE--1,CA--2,CH--1,DE--1,US--1
2 2 CA--1,US--2,CH--1
Here is what you need:
select seq_id, id, group_concat(concat(country_code, '--', qtd))
from (
select ma.seq_id, ma.id,
mgr.country_code, count(*) qtd
from music_artists ma
inner join music_album_artists maa
on ma.id = maa.artist_id
inner join media_geo_restrict mgr
on maa.album_id = mgr.album_id
where ma.seq_id > 0 and ma.seq_id < 10000
group by ma.seq_id, ma.id, ma.name,
mgr.country_code
) tb
group by seq_id, id
Here is the working sample: http://sqlfiddle.com/#!9/ff8b5/8
Try this and tell me:
SELECT a.seq_id, a.id, GROUP_CONCAT(cnt) AS cnt
FROM music_artist AS a,
(
SELECT ma.artist_id, CONCAT_WS('-', mgr.country_code, count(mgr.media_id)) AS cnt
FROM music_album_artists AS ma
JOIN media_geo_restrict AS mgr ON ma.album_id = mgr.album_id
GROUP BY mgr.country_code
) AS count_table
WHERE a.seq_id > 0 and a.seq_id < 10000
and a.id=count_table.artist_id
group by a.id