MySQL query summing records for users - mysql

I'm using MySQL with phpmyadmin -- which I only started to use today. If y'all can help me with this query you will create some major happiness:
My objective: to identify which users of status "userEnabled" have >3 records from the goals table associated with them.
userID is a field that relates the tables.
TABLE NAMES: users, goals
I think this would be the beginning of the query:
SELECT * FROM `users` WHERE `userEnabled`=1
Please let me know any details needed.

You need to join record from goals where the userid matches. Filter on the enabled flag, then count the results. Something like:
select * from users
INNER JOIN goals ON users.userID = goals.userID
WHERE user.userEnabled = 1
GROUP BY user.userID
HAVING count(user.userID) > 3

Related

How to get opposite results of a specific sql query?

I have 3 tables which are divided in users, user_courses and course.
I wanted to create 2 queries:
One query to return the subscribed courses of a specific user
Another query to return the unsubscribes courses of a specific user
I got the first query done but I canĀ“t make the 2nd query work.
I tried to negate the conditions and got the same rows multiple times.
SELECT
course.course_id,course_name,course_owner,course_date,course_time
FROM
course, users, user_courses
WHERE
usershortcut = "mmuster"
AND user_courses.user_id = users.user_id
AND user_courses.course_id = course.course_id
This is the first query which gives out all the subscribed courses of a user and I have no clue how to reverse it so I get the unsub courses of that user.
If the query you mention gives you the subscribed courses, for the second one you can use a filtering condition as in:
select *
from course
where course_id not in (
SELECT course.course_id
FROM course,users,user_courses
WHERE usershortcut="mmuster" and user_courses.user_id = users.user_id
and user_courses.course_id = course.course_id
)

use COUNT(*) values from one table to another

Suppose I have two tables, users and posts. Posts has the following fields, userid, postid, etc and userid can appear multiple times as one user can write multiple posts....I'm just trying sort the users table based off the # of occurrences per userid in the posts table. I can get the # of occurrences per user using this
SELECT userid, COUNT(*)
FROM posts
GROUP BY userid;
I would like to use the values under COUNT(*) column, maybe add it to my other table because then I can simply to something like this
SELECT * FROM users
ORDER BY newcolumn ASC;
but I'm having trouble doing that. Or can I do it without having to add an extra column? Hints please. Thanks
Left join is the key here!
SELECT users.userid,count(posts.userid) AS total_count
FROM users
LEFT JOIN posts on posts.userid = users.userid
GROUP BY users.userid
ORDER BY total_count DESC;
We are taking the left join on two tables with same user_id and we are counting the total number of posts per user using group by. Finally sort by count and show results.
try an left join:
select users.userid, [user fields],count(postid) as posts_count
from users
left join posts on posts.userid = users.userid
group by users.userid,[user fields]
order by posts_count desc.
You want to select users (FROM users) but you want to sort based on criteria in another table (COUNT(*) FROM posts) -- therefore you need to use a JOIN
Off-hand I can't seem to recall if "JOIN" or "RIGHT JOIN" or "FULL JOIN" is what you need if you wanted to get a cartesian product of the tables then group and aggregate on a single field, but I can avoid the need to remember with a subquery (hopefully someone will soon post a smaller and smarter answer):
SELECT users.* FROM users
JOIN (
SELECT userid, COUNT(*) as count
FROM posts
GROUP BY userid
) as subquery ON users.id = subquery.userid
ORDER BY subquery.count
Note: I haven't tested this query, but it looks good to me. Again: hopefully someone will post a better answer soon as I'm not doing my due dilligence, but you definitely need a JOIN :)
You could add a post_count column to the users table, but you would also have to update that count column every time a user creates a new post and you would have to build that logic into your application.
Otherwise, it looks like the answer from FallAndLearn will get you what you need.

Join query for getting non matching records

I have a question regarding MySql statement. I have 2 tables, record and training. Training table contains list of all courses, and record table contains list of courses that the user have attend. Training table is below
Record table format:
I want to get list non attending courses of each user. For eg: From the above table structure, user 277 is attending 130,167,128 & 2. So the non attending courses of user 277 is 3,4,5,7,8,9,147,11,12.
How can i write sql statement for getting the above result? Please help
Its something like this
SELECT * FROM training t WHERE t.id NOT IN (select trainingId from record where UserId=277 && piId=1) && t.status=1 ORDER BY t.categoryId
select id from training where id not in ( select trainingid from record where userid = yourid)
Get a list of users, cross join that with the training courses and then LEFT OUTER JOIN that to the table of training courses done by users. Us the WHERE clause to check there wasn't a match to the last table.
Untested, but something like this:-
SELECT sub_user.UserId, t.id
FROM
(
SELECT DISTINCT UserId from record
) sub_user
CROSS JOIN Training t
LEFT OUTER JOIN Record r
ON sub_user.UserId = r.UserId
AND r.trainingId = t.id
WHERE r.id IS NULL
If you have a table of users (which you probably do) then you could eliminate the sub query and replace it with that table.

SQL Query: Must go through table, COUNT certain entries, and use that result as Column name in rest of Query

I am having trouble making a query which must behave as following:
Imagine a table named "Users" with these column names: id, name, vote.
The vote column holds the id of a row. For example, if I am id = 0, and you are id = 1, I wish to vote for you so my vote entry holds "1", you wish to vote for yourself so your's too holds "1".
I want a query which returns these columns: id, name, vote, totalVotes.
So it should count all the votes that have your id and place that number under total votes.
My "totalVotes" would be "0", and your's would be "2".
The problem is that I do not understand how to go through the entire table, calculate the total number of votes for a user, and then repeat for every user.
Any tips would be greatly appreciated and if it is difficult to understand feel free to tell me what part I should word better.
select
u1.id, u1.name, u1.vote,
ifnull(u2.totalVotes, 0) as totalVotes
from Users as u1
left outer join (
select u2.vote as id, count(*) as totalVotes
from Users as u2
group by u2.vote
) as u2 on u2.id = u1.id
sql fiddle demo
a bit of explanation:
I'm using a subquery, grouping records from Users by vote, so I'll have a table where I have count of votes for each user
After that join Users with this table
in the final recordset I'm using ifnull to display 0 for users who have no votes.
This, I believe, the fastest way to do this query in MySQL (without window functions), here you can see sql fiddle for only 1280 rows with my query and Carter's one using subquery.
sql fiddle demo
Results:
My query: 4ms
Carter's query with subquery: 832ms
This would be one way...
select
u1.id,
u1.name,
u1.vote,
(select count(*) from Users as u2 where u2.vote = u1.id) as totalVotes
from
Users as u1;
See: this SQL Fiddle for an exmaple.
Addendum: As Roman points out, when it comes to efficiency, his answer is clearly the better of our two. In general joins are more efficient than subqueries.

MySQL returning results from one table based on data in another table

Before delving into the issue, first I will explain the situation. I have two tables such as the following:
USERS TABLE
user_id
username
firstName
lastName
GROUPS TABLE
user_id
group_id
I want to retrieve all users who's first name is LIKE '%foo%' and who is a part of a group with group_id = 'givengid'
So, the query would like something like this:
SELECT user_id FROM users WHERE firstName LIKE '%foo'"
I can make a user defined sql function such as ismember(user_id, group_id) that will return 1 if the user is a part of the group and 0 if they are not and this to the WHERE clause in the aforementioned select statement. However, this means that for every user who's first name matches the criteria, another query has to be run through thousands of other records to find a potential match for a group entry.
The users and groups table will each have several hundred thousand records. Is it more conventional to use the user defined function approach or run a query using the UNION statement? If the UNION approach is best, what would the query with the union statement look like?
Of course, I will run benchmarks but I just want to get some perspective on the possible range of solutions for this situation and what is generally most effective/efficient.
You should use a JOIN to get users matching your two criteria.
SELECT
user_id
FROM
users
INNER JOIN
groups
ON groups.user_id = users.users_id
AND groups.group_id = given_id
WHERE
firstName LIKE '%foo'
You don't need to use either a UNION or a user-defined function here; instead, you can use a JOIN (which lets you join one table to another one based on a set of equivalent columns):
SELECT u.user_id
FROM users AS u
JOIN groups AS g
ON g.user_id = u.user_id
WHERE g.group_id = 'givengid'
AND u.firstName LIKE '%foo'
What this query does is join rows in the groups table to rows in the users table when the user_id is the same (so if you were to use SELECT *, you would end up with a long row containing the user data and the group data for that user). If multiple groups rows exist for the user, multiple rows will be retrieved before being filtered by the WHERE clause.
Use a join:
SELECT DISTINCT user_id
FROM users
INNER JOIN groups ON groups.user_id = users.user_id
WHERE users.firstName LIKE '%foo'
AND groups.group_id = '23'
The DISTINCT makes sure you don't have duplicate user IDs in the result.