Count records from two tables with foreign keys - mysql

Suppose I have these MySql tables:
TABLE_PEOPLE
id
name
1
John
2
Albert
3
Joanna
4
Mike
5
Norton
TABLE_COLOR
id
people_id
colors
1
1
Green
2
1
Red
3
3
Yellow
4
3
Blue
5
2
Green
6
4
Red
7
5
Grey
8
3
White
9
4
Black
10
1
Black
TABLE_FRUIT
id
people_id
fruits
1
1
Lemon
2
2
Apple
3
3
Tangerine
4
5
Orange
5
2
Banana
6
1
Apple
7
5
Lemon
8
2
Orange
9
3
Watermelon
10
4
Banana
What I'd like to have is a query with numbers of occurrences of colors and fruits for each person:
RESULTS
| name| count_colors | count_fruits |
|:----:|:----:|:-------:|
|John|3|2|
|Albert|1|3|
|Joanna|3|2|
|Mike|2|1|
|Norton|1|1|
I'm trying to use this query, but it returns some inconsistent numbers:
SELECT
TABLE_PEOPLE.name AS name,
COUNT(TABLE_COLOR.people_id) AS count_colors,
COUNT(TABLE_FRUIT.people_id) AS count_fruits
FROM TABLE_PEOPLE
LEFT JOIN TABLE_COLOR ON TABLE_COLOR.people_id = TABLE_PEOPLE.id
LEFT JOIN TABLE_FRUIT ON TABLE_FRUIT.people_id = TABLE_PEOPLE.id
GROUP BY TABLE_PEOPLE.id
ORDER BY TABLE_PEOPLE.id
Any idea?

The issue with your current query is that you are using the COUNT function to count the number of occurrences of people_id in TABLE_COLOR and TABLE_FRUIT. However, this will not give you the correct result because the COUNT function will only return the number of non-NULL values, and since you are using LEFT JOIN, all of the people_id values will be non-NULL, so COUNT will always return the same value for each person.
To fix this issue, you can use a subquery in your SELECT clause to count the number of occurrences of colors and fruits for each person:
SELECT
TABLE_PEOPLE.name AS name,
(SELECT COUNT(*) FROM TABLE_COLOR WHERE TABLE_COLOR.people_id = TABLE_PEOPLE.id) AS count_colors,
(SELECT COUNT(*) FROM TABLE_FRUIT WHERE TABLE_FRUIT.people_id = TABLE_PEOPLE.id) AS count_fruits
FROM TABLE_PEOPLE
ORDER BY TABLE_PEOPLE.id
This will return the correct number of occurrences of colors and fruits for each person.

You should join to subqueries which find the various counts:
SELECT
p.name,
COALESCE(c.cnt, 0) AS count_colors,
COALESCE(f.cnt, 0) AS count_fruits
FROM TABLE_PEOPLE p
LEFT JOIN
(
SELECT people_id, COUNT(*) AS cnt
FROM TABLE_COLOR
GROUP BY people_id
) c
ON c.people_id = p.id
LEFT JOIN
(
SELECT people_id, COUNT(*) AS cnt
FROM TABLE_FRUIT
GROUP BY people_id
) f
ON f.people_id = p.id
ORDER BY
p.id;
Your exact problem is happening because of the double join to the colors and fruits table, which results in multiplication of records.

Related

How to prevent duplication on the second table Using inner Joins and the Count

SELECT T.column_11,
count(column_11) count
FROM wp_tablesome_table_4695 T
JOIN wp_fea_submissions S ON T.column_2 = S.title
group BY T.column_11
wp_tablesome_table_4695
column 2 | column 11
1 | location 1
2 | location 2
3 | Location 3
wp_fea_submissions
title
1
1
2
3
Result
column 11| count
1 | 2
2 | 1
3 | 1
The count result is also counting the duplicate S.Title how to prevent counting the Duplicate
The count need to be done inside a subquery.
SELECT T.column11,
count(column11) count
FROM wp_tablesome_table_4695 T
INNER JOIN (select distinct title
from wp_fea_submissions
) S ON T.column2 = S.title
group BY T.column11;
Or
with cte as ( select distinct title
from wp_fea_submissions
) select wp.column11, count(wp.column11) as cnt
from cte
inner join wp_tablesome_table_4695 wp on wp.column2=cte.title
group by wp.column11;
https://dbfiddle.uk/iVprcr8z

MYSQL Get random 2 Cars, all colors (LEFT JOIN)

I have a table, Cars,
CarID | Car
1 Taurus
2 Ranger
3 Charger
and CarColors with colors for each car.
ColorID | CarID | Color
1 1 White
2 1 Blue
3 2 Black
4 1 Red
5 2 Pink
6 3 Orange
I want to get a random two cars, and all colors for those cars. I tried
SELECT * FROM Cars C
LEFT JOIN CarColors CC ON C.CarID = CC.CarID
ORDER BY RAND()
LIMIT 2
But this, understandably, returns two rows.
I tried a subquery, something like
SELECT * FROM Cars C
LEFT JOIN CarColors CC ON C.CarID = CC.CarID
WHERE C.CarID IN (SELECT CarID FROM Cars
ORDER BY RAND()
LIMIT 2)
But MYSQL doesn't support LIMIT within subqueries.
When I try to search for this, I get answers for limiting the JOIN's results (like 1 color for each car)
If your MySQL version support ROW_NUMBER window function, you can try this
SELECT * FROM
(
SELECT *,ROW_NUMBER() OVER(ORDER BY RAND()) rn
FROM Cars
) C LEFT JOIN CarColors CC ON C.CarID = CC.CarID
WHERE rn <= 2
sqlfiddle
Another way is you can just use a subquery to get random cars then do JOIN
SELECT * FROM
(
SELECT *
FROM Cars
ORDER BY RAND()
LIMIT 2
) C LEFT JOIN CarColors CC ON C.CarID = CC.CarID

Filter count table query

i have 2 tables as following.
User
id name
---------------
1 john
2 raju
3 manu
4 raghu
friendtable
id userid recvId
------------------------
1 1 2
2 1 3
3 2 3
4 3 4
Is it possible to filter users by their friends count from these tables.Please help me.
For eg :- range >=3 will result : john,manu
range >3 and range <2 will result : raju
range <2 result : raghu
Do a UNION ALL to get all id's from friendstable in one column. Join users table with that result.
Do a GROUP BY, adjust HAVING to decide what to return, e.g. at least 3 times etc.
select u.name
from users
join (select userid as id from friendtable
union all
select recvId as id from friendtable) f
on u.id = f.id
group by u.name
having count(*) >= 3
SELECT name FROM user a,friendtable b WHERE a.id=b.id AND b.recvid>=3
SELECT name FROM user a,friendtable b WHERE a.id=b.id and b.recvid>3 AND b.recid<2
SELECT name FROM user a,friendtable b WHERE a.id=b.id AND b.recid<2

How To write a SQL Select Query for this problem?

I have four tables: groups, users, votes, follows.
The structures of these tables are
groups
g_id g_title g_content
1 t1 content1
2 t2 content2
users
u_id u_groupid
1 1
2 1
3 2
4 2
5 2
votes
v_id v_userid v_groupid v_votes
1 1 1 1
2 1 2 1
3 2 2 1
4 3 2 1
5 3 1 1
follows
f_id f_userid f_groupid
1 1 1
2 2 1
3 2 2
4 3 1
5 3 2
The groups table records the basic information of a "group".
The users table keeps the relationship between users and groups, that is, if the user A belongs to groups B, then there will be a record in the user table.
The votes table means the supportive attitude that a user holds to a group.
If user A is interested in group A, then add a entry into the Follows table.
Now my problem is how to write one select statement to query the number of users, the number of votes and the number of followers of each group.
I want the query result likes this
g_id num_users unm_votes num_followers
1 2 2 3
2 3 3 2
By the way, my database is Mysql 5.0.51b.
If you want in 1 query, something like this will help you
SELECT g_id,
d1.num_users,
d2.unm_votes,
d3.num_followers
FROM groups gg
LEFT JOIN (SELECT g_id,
COUNT(u.u_id) AS num_users
FROM groups g
LEFT JOIN users u
ON u.u_groupid = g.g_id
GROUP BY g_id) d1
ON d1.g_id = gg.g_id
LEFT JOIN (SELECT g_id,
COUNT(v.v_userid) AS unm_votes
FROM groups g
LEFT JOIN votes v
ON v.v_groupid = g.g_id
GROUP BY g_id) d2
ON d2.g_id = gg.g_id
LEFT JOIN (SELECT g_id,
COUNT(f.f_userid) AS num_followers
FROM groups g
LEFT JOIN follows f
ON f.f_groupid = g.g_id
GROUP BY g_id) d3
ON d3.g_id = gg.g_id
GROUP BY gg.g_id
For the user count by group:
select g_id,count(u.uid) user_count from groups g, users u
where u.groupid = g.g_id
group by g_id
May want to read up on group by.

SQL Counting sums of rows

I have 2 tables.
Table 1: Fruits
id (int, autoincreasing, primary key)
some other junk
Table 2: Customers
has a 'fruit' column, this column contains an id from the fruit table.
i want to query all the customers, and come up with a list of all the fruit ID's and the number of times they are in use.
So this set up:
Fruits has
id name
1 orange
2 banana
3 apple
Customers has 6 rows like:
id fruit
1 1
2 1
3 2
4 2
5 2
6 3
Trying to write a query that Will give me:
fruit id purchase count
1 2
2 4
3 1
Try this
SELECT f.id as fruit_id, COUNT(1) AS purchase_count
FROM FRUITS f LEFT JOIN CUSTOMERS c
ON F.ID = c.fruit
GROUP BY f.id
Should just be a simple aggregate...
SELECT fruit_id, COUNT(fruit_id) AS purchase_count
FROM customers
GROUP BY fruit_id
ORDER BY fruit_id ASC;
untested
SELECT id, SUM(fruit) as "fruit id", "purchase count"
FROM Customers
GROUP BY id;