I have two tables in mysql database
groups
id|name
_______
1 |red
2 |blue
3 |green
4 |white
and users
id|name |group
_______________
1 |joe |1
2 |max |1
3 |anna |2
4 |lisa |2
So... joe and max are in the "red" group, anna and lisa are in the "blue" group.
How can I make simple listing of groups which would contain the number of
persons in that group
For example
red - 2
blue - 2
green - 0
white - 0
Most the other answers are basically correct, but forgot an important detail: GROUP is a reserved word in SQL, so your column name must be escaped:
SELECT groups.name, COUNT(*) AS total_members
FROM groups
LEFT OUTER JOIN users
ON users.`group` = groups.id
GROUP BY groups.id
check if this works....
SELECT COUNT(*), groups.name FROM groups, users WHERE users.group=groups.id GROUP BY groups.name
UPDATE
SELECT groups.name, COUNT(users.*) FROM groups LEFT JOIN users
ON groups.id=users.group GROUP BY groups.name
this will keep the colors even if they dont have any name related
Give this a try:
select g.name, count(u.id) from groups g
left join users u on g.id = u.group
group by g.id, g.name
Try this
SELECT COUNT(g.id) as count, g.name
FROM groups as g
LEFT JOIN users as u
ON u.group = g.id
GROUP BY g.id
This should work
SELECT g.*, COUNT(DISTINCT u.id) FROM `groups` g
INNER JOIN `users` u on g.id = u.group
GROUP BY u.id
maybe this should work
SELECT g.name, COUNT( u.id ) AS Totoal
FROM `groups` g
INNER JOIN `users` u ON g.id = u.group
GROUP BY g.id
Related
I have two tables
**users**
id name
1 Name1
2 Name2
**tasks**
id user_id title
1 1 Task1
2 1 Task2
3 2 Task3
My request:
SELECT
U.*,
COUNT(T.id) AS tasks_total
FROM
`#__users` AS U
LEFT JOIN
`#__tasks` AS T
ON
U.id = T.user_id
I think something wrong here...
I wan't to get results:
id name tasks_total
1 Name1 2
2 Name2 1
Thanks!
You forgot to group the result by id
SELECT
U.*,
COUNT(T.id) AS tasks_total
FROM
`#__users` AS U
LEFT JOIN
`#__tasks` AS T
ON
U.id = T.user_id
group by U.id
demo on sqlfiddle
You're mixing line functions and aggregate functions. One way around this is to have the aggregation done in a subquery:
SELECT
U.*,
tasks_total
FROM
`#__users` AS U
LEFT JOIN
(SELECT user_id, COUNT(*) AS tasks_total
FROM `#__tasks`
GROUP BY user_id) AS T
ON
U.id = T.user_id
I have the two tables:
user_groups
id name created_user
1 gn1 3
2 gn2 3
user_group_has_users
group_id user_id
2 5
2 6
I want to count the users per group and an output similar this:
id name user_count
2 gn2 2
1 gn1 0
I tried this query
select g.*,
count(cg.user_id) as user_count
from user_groups as g
left join user_group_has_users as cg on cg.user_group_id = g.id
where g.created_user = 3
But it only returns one row. I do not understand why this happening.
Please help me on this.
Use this query
SELECT g.* ,COUNT(cg.user_id) AS user_count
FROM user_groups g
LEFT JOIN user_group_has_users cg ON cg.group_id = g.id
WHERE g.created_user = 3
GROUP BY g.id
ORDER BY user_count DESC ;
Left join with where condition is nothing but inner join. You may want as
select
ug.id,
ug.name,
count(ughu.user_id) as user_count
from user_groups ug
left join user_groups_has_users ughu on ughu.group_id = ug.id
and ug.created_user = 3
group by ug.id
order by user_count desc ;
If you still want to filter the data with the created_user = 3 then use inner join and move the condition to where clause
Be careful with aggregates and JOINs. In some cases the numbers are inflated.
See if this works for you:
select g.*,
( SELECT count(*)
FROM user_group_has_users
WHERE user_group_id = g.id
) AS user_count
from user_groups as g
where g.created_user = 3
I'm trying to get my head around this query but one of the records still keeps popping up. In summary, my intention is to show group members on the left and names from a phonebook which are not included in the group on the right. That way the user can select them and add them to the group.
user_id firstname group_id grpname
------- --------- -------- ----------
1 Luker 3 Abc
2 John 1 Some Group
3 Sam 2 Awesome Group
4 Mitch 1 Some Group
4 Mitch 2 Awesome Group
5 Rocky (NULL) (NULL)
6 Pops (NULL) (NULL)
The unique thing is that if one of the users is a part of multiple groups (user_id 4), their name should not be shown in the phonebook at all since it would already be placed in the list of existing members.
-- Query for group_id 2
SELECT user.id user_id, user.firstname, grp.id group_id, grp.grpname FROM agi_user user
LEFT JOIN agi_group_user gu ON user.id = gu.user_id
LEFT JOIN agi_groups grp ON gu.group_id = grp.id
WHERE grp.id IS NULL OR grp.id != 2
GROUP BY user.id
but for some reason the user Mitch still keeps popping up.
user_id firstname group_id grpname
------- --------- -------- ----------
1 Luker 3 Abc
2 John 1 Some Group
4 Mitch 1 Some Group
5 Rocky (NULL) (NULL)
6 Paps (NULL) (NULL)
Edit:: The output I need is
user_id firstname group_id grpname
------- --------- -------- ----------
1 Luker 3 Abc
2 John 1 Some Group
5 Rocky (NULL) (NULL)
6 Paps (NULL) (NULL)
Basically, to I want to get all users not a part of that group including NULL. But since one user is a part of multiple groups, her record still comes up when it shouldn't because that other group probably has a group_id of 3 or 4 (or any other besides 2).
You can use NOT EXIST to check if there are no group/user rows at all for group 2 and the given user:
SELECT
user.id user_id,
user.firstname,
grp.id group_id,
grp.grpname
FROM
agi_user user
LEFT JOIN agi_group_user gu ON user.id = gu.user_id
LEFT JOIN agi_groups grp ON gu.group_id = grp.id
WHERE
NOT EXISTS (
SELECT 'x' FROM agi_group_user x
WHERE
x.user_id = user.user_id and
x.group_id = 2)
GROUP BY
user.id
Note that if a user is not in group 2, but is in two other groups, he will show up 1 time in this result and only one of the groups he is in is returned. To fix that, you can add grp.id to the GROUP BY clause, or maybe you can use GROUP_CONCAT to return a list of group names in a single field.
Alternatively, this should work too, and in MySQL it might even perform better since it sucks at subqueries. Personally I think it is semantically less clear what is going on, though.
It joins the user/groups table a second time, but adds the group_id (2) to the join. If there are no rows returned for this table, then the user is not in group 2. The comment regarding GROUP_CONCAT applies to this query as well.
SELECT
user.id user_id,
user.firstname,
grp.id group_id,
grp.grpname
FROM
agi_user user
LEFT JOIN agi_group_user gu ON user.id = gu.user_id
LEFT JOIN agi_groups grp ON gu.group_id = grp.id
LEFT JOIN agi_group_user x ON user.id = x.user_id and x.group_id = 2
WHERE
x.group_id IS NULL
GROUP BY
user.id
If I understood correctly, you want this: "All users that are not in group 2"
This is called an anti-semijoin (or just anti-join) and can be done with a LEFT JOIN /IS NULL query:
SELECT u.id user_id, u.firstname
FROM agi_user AS u
LEFT JOIN agi_group_user AS gu
ON u.id = gu.user_id
AND gu.group_id = 2
WHERE gu.group_id IS NULL ;
or with a NOT EXISTS subquery:
SELECT u.id user_id, u.firstname
FROM agi_user AS u
WHERE NOT EXISTS
( SELECT 1
FROM JOIN agi_group_user AS gu
WHERE u.id = gu.user_id
AND gu.group_id = 2
) ;
say i had the following tables
user_table
id username
1 abc
2 def
3 ghij
courses_table
id title
1 csc
2 math
3 syn
user_courses
user_id course_id
2 1
1 3
2 3
i want to select the username whos taking course 1 AND 3 ,
not at least 1 or 3 , i mean both 1 and 3
i've tried the following mysql queries
SELECT DISTINCT u.* FROM user_table as u LEFT JOIN user_courses as uc ON uc.user_id = u.id WHERE uc.course_id = 1 AND uc.course_id=3;
SELECT DISTINCT u.* FROM user_table as u LEFT JOIN user_courses as uc ON uc.user_id = u.id WHERE uc.course_id IN (1,3);
SELECT DISTINCT u.* FROM user_table as u LEFT JOIN user_courses as uc ON uc.user_id = u.id WHERE uc.course_id IN (1,3) AND uc.user_id = u.id ;
the first and third queries executed with no results shown , and the second one show all users who had at least course_id 1 or 3
if you are wondering why am i using the LEFT JOIN , this is because i need to join table's results , and the above line of code is just an example , and im using to get data from about 9 tables using the LEFT join .
any help please ? thanks
SELECT DISTINCT u.* FROM user_table as u LEFT JOIN user_courses as uc ON uc.user_id = u.id WHERE uc.course_id IN( 1,3) AND uc.user_id = 2 ";
this show me the result i want , its output "def" ,
but i can't use the user_id as a static value ( number 2 in this example )
This problem is called Relational Division
SELECT a.id, a.username
FROM user_table a
INNER JOIN user_courses b
ON a.id = b.user_ID
WHERE b.course_ID IN (1,3)
GROUP BY a.id, a.username
HAVING COUNT(*) = 2
SQL of Relational Division
If course_ID is not unique for every users considering that the user have retake the course, a DISTINCT keyword is needed to coung unique courses,
SELECT a.id, a.username
FROM user_table a
INNER JOIN user_courses b
ON a.id = b.user_ID
WHERE b.course_ID IN (1,3)
GROUP BY a.id, a.username
HAVING COUNT(DISTINCT b.course_ID) = 2
SQLFiddle Demo
OUTPUT
╔════╦══════════╗
║ ID ║ USERNAME ║
╠════╬══════════╣
║ 2 ║ def ║
╚════╩══════════╝
please try this:
SELECT
U.id,
U.username
FROM
user_courses UC
INNER JOIN user_table U
ON UC.`user_id` = U.`id`
WHERE UC.`course_id` = 1
OR UC.`course_id` = 3
GROUP BY U.`id`
HAVING COUNT(*) > 1
I have a table named friends;
friends
id uid fid
1 1 2 (1 is a friend of 2 and vice versa)
2 1 3 (1 is a friend of 3 and vice versa)
3 4 1 (1 is a friend of 4 and vice versa)
4 5 1 (1 is a friend of 5 and vice versa)
And a corresponding table for users;
users
uid name
1 mike
2 john
3 karl
4 mary
5 tony
This doesn't seem to do the trick:
SELECT name FROM users LEFT JOIN friends ON friends.uid=users.uid WHERE friends.uid='1' OR friends.fid='1'
What should my query be to get all the names of mike's friends?
This should do it just fine with a single, easy to index, query;
SELECT name FROM users u
JOIN friends f
ON u.uid = f.uid OR u.uid = f.fid
WHERE (f.uid=1 OR f.fid=1)
AND u.uid<>1;
Demo here.
Untested:
SELECT name from friends LEFT JOIN users on users.uid=friends.fid where friends.uid=1 UNION
SELECT name from friends LEFT JOIN users on users.uid=friends.uid where friends.fid=1
This may look a little strange if anyone is ever friends with themselves.
try one of these:
SELECT a.uid as UserID,
a.`Name` as UserName,
c.`Name as FriendsName
FROM users a LEFT JOIN friends b on a.uid = b.uid
LEFT JOIN users c on b.fid = c.uid
OR
SELECT a.uid as UserID,
a.`Name` as UserName,
GROUP_CONCAT(c.`Name`) as FriendsList
FROM users a LEFT JOIN friends b on a.uid = b.uid
LEFT JOIN users c on b.fid = c.uid
GROUP BY a.uid
As in your prequel question, you need to cover both foreign keys to the user table to get all his friends:
SELECT users.*
FROM (
SELECT uid FROM friends WHERE fid = 1
UNION ALL
SELECT fid FROM friends WHERE uid = 1
) f
JOIN users USING (uid)
Switch friends and users in your query and I think you'll get what you want.
In other words:
SELECT name FROM friends LEFT JOIN users ON friends.uid=users.uid WHERE friends.uid='1' OR friends.fid='1'
I think this is right SELECT name FROM users LEFT JOIN friends ON friends.uid=users.uid WHERE friends.uid=1 OR friends.fid=1