I have a table with users, a table with assignments, and a table with tasks each associated with an assignment and user. I want to get the list of students that have a task on a given assignment. (I've tried to simplify this DB sample as much as possible for my question.)
Here's an SQL Fiddle: http://sqlfiddle.com/#!9/625a13/1
For reference, here's what the DB structure looks like:
CREATE TABLE users (
id SERIAL,
name VARCHAR(32),
PRIMARY KEY (id)
);
CREATE TABLE assignments (
id SERIAL,
title VARCHAR(45),
assigned_by_user_id INT,
PRIMARY KEY (id)
);
CREATE TABLE tasks (
id SERIAL,
user_id INT,
assignment_id INT,
complete INT,
PRIMARY KEY (id)
);
INSERT INTO users VALUES (1, 'Student Joe'), (2, 'Student Fred'), (3, 'Teacher Bob');
INSERT INTO assignments VALUES (1, 'Math Homework', 3), (2, 'History Homework', 3), (3, 'Science Homework', 3);
INSERT INTO tasks VALUES (1,1,1,1), (2,1,2,1), (3,1,3,0), (4,2,1,1), (5,2,2,0), (6,2,3,0);
And here's a sample of a query from this data:
SELECT a.id, a.title, u.name AS teacher_name, '' AS students_included,
(COUNT(CASE WHEN t.complete = 1 THEN t.id ELSE NULL END)/COUNT(t.id)*100) AS percent_complete
FROM assignments AS a
JOIN users AS u ON a.assigned_by_user_id = u.id
LEFT JOIN tasks AS t ON a.id = t.assignment_id
GROUP BY a.id
Here's a screenshot of what I have:
Here's my target result:
How can I have the query return the student names that are associated to those assignments? In some cases, there might not be any tasks (no students), in some cases one student, in some cases multiple students. I'd like to somehow get an array / CSV list of student names in the associated column.
(I know I could do separate queries for each line - for instance in PHP as I loop through the results - and get this result, but that would be slow, cumbersome, and resource intensive - I'd like to get the student name values with a single MySQL query if at all possible - I just can't think of how to do it.)
You may use GROUP_CONCAT (similar to LISTAGG in Oracle), and would require one more join with USERS table to pull students' names
SELECT a.id, a.title, u.name AS teacher_name, GROUP_CONCAT(stu.name) AS students_included,
(COUNT(CASE WHEN t.complete = 1 THEN t.id ELSE NULL END)/COUNT(t.id)*100) AS percent_complete
FROM assignments AS a
JOIN users AS u ON a.assigned_by_user_id = u.id
LEFT JOIN tasks AS t ON a.id = t.assignment_id
LEFT JOIN users AS stu ON stu.id = t.user_id
GROUP BY a.id, a.title, u.name
Do not forget adding columns to GROUP BY clause.
You need to use a GROUP_CONCAT and also join another user table
SELECT a.id, a.title, u.name AS teacher_name, GROUP_CONCAT(us.name) AS students_included,
(COUNT(CASE WHEN t.complete = 1 THEN t.id ELSE NULL END)/COUNT(t.id)*100) AS percent_complete
FROM assignments AS a
JOIN users AS u ON a.assigned_by_user_id = u.id
LEFT JOIN tasks AS t ON a.id = t.assignment_id
JOIN users AS us ON t.user_id = us.id
GROUP BY a.id
I think I may have figured this out...
SELECT a.id, a.title, u.name AS teacher_name, GROUP_CONCAT(u_s.name SEPARATOR ', ') AS students_included,
(COUNT(CASE WHEN t.complete = 1 THEN t.id ELSE NULL END)/COUNT(t.id)*100) AS percent_complete
FROM assignments AS a
LEFT JOIN tasks AS t ON a.id = t.assignment_id
JOIN users AS u ON a.assigned_by_user_id = u.id
LEFT JOIN users AS u_s ON t.user_id = u_s.id
GROUP BY a.id
Still playing with it... but someone may have a better idea...
I'm trying to join multiple table to get single row result for each id. This result will be send to angular UI
I have 3 tables user, friends and trip
A user can have multiple friends but one trip
I like to get all details corresponding to a user in one row, probably friends as field like an array?
This is how my table looks.
http://sqlfiddle.com/#!9/0879d/2
https://gist.github.com/tomalex0/9dee4fff85583732e7d0
group_concat should do the trick for you:
SELECT u.*, t.*, friendlist
FROM user u
LEFT JOIN trip t ON u.id = t.user_id
LEFT JOIN (SELECT user_id, GROUP_CONCAT(CONCAT (name, '- ', email)) friendlist
FROM friends
GROUP BY user_id) f ON f.user_id = u.id
How can I get the name of students by using the section and year_level as arguments? Below is the ERD of my database.
select u.fname
from users u
join students s on u.user_id = s.user_id
join sections sec on s.section_id = sec.section_id
where sec.section_id = 1
and sec.year_level_section = 1
You don't even need to join level table. Actually, you don't need that table at all.
I'm trying to get a list of 'contacts' for a specified user id.
Let says my user id is 1, i need to get the list of ids of my my contacts from chat-contactlist then get all the infos for each id.
All users' id, name and contact information
Table usr: uid, rname, phonenumber
Online status and other stuff
Table chat-usr: uid, nickname, online_status
Containing user id and the user id of each contact this user have :
Table chat-contactlist: uid, cid (cid = The id of the person who's int he "uid" user list
So I need the name, the nickname, the online_status for all the 'cid' for a specified 'uid'... Dont know i read a tutorial about left join but it seams complex to merge multiple tables, anyone wanna try? Any recommendation?
Thank you
EDIT
Changing name by rname because name is a reserved word for SQL.
This is a 3-table join where you have a many-to-many relationship defined by the linker table chat-contactlist:
SELECT u.name username, c.nickname chat_username, c.online_status
FROM chat-contactlist cc
JOIN usr u ON (u.uid = cc.uid)
JOIN chat-usr c ON (c.uid = cc.cid);
This is an explicit join. If you are looking to select a specific user, you would add that in WHERE clauses afterward.
SELECT u.name username, c.nickname chat_username, c.online_status
FROM usr u, chat-usr c, chat-contactlist cc
WHERE cc.uid = u.uid
AND cc.cid = c.uid;
This is an implicit join, where the tables are related by equality in WHERE statements. It isn't recommended to use but I find them sometimes easier to read.
More info:
Basic many-to-many left join query
Explicit vs Implicit Joins
SELECT ccl.uid,
Name = u.Name,
Nickname = cu.nickname,
OnlineStatus = cu.onlinestatus
FROM chat-contactlist ccl
JOIN chat-usr cu ON ccl.cid = cu.uid
JOIN usr u ON u.uid = cu.uid
Where ccl.uid = #uid /* your filter here */
I am using a system I didn't create. The system has 3 main tables:
users, courses, and usergroups. I am using an extra table called coursehits.
It's a MySQL DB, 5.0. There aren't any relationships in the DB, so users are assigned to courses by simply adding an entry to usergroups (course_id and user_id) from the courses and users table. Likewise if they start a course an entry is made to coursehits.
I am trying to count the number of users in coursehits and usergroups for reporting data. So far I have the following which doesn't count correctly in one query but this doesn't count correctly, the results are much too high:
SELECT DISTINCT
c.course_name,
COUNT(ug.user_id) AS "Enrolled",
COUNT(ch.user_id) as "Started"
FROM courses c, usergroups ug, coursehits ch, users u
WHERE ch.user_id = u.id
AND ug.user_id = u.id
AND ug.course_id = c.id
AND ch.page_id != 4
GROUP BY 1
Before I was doing the following individually which does work:
SELECT DISTINCT c.course_name, COUNT(ug.user_id) AS "Enrolled"
FROM courses c, usergroups ug
WHERE ug.course_id = c.id
GROUP BY 1
Where as now I am trying to report the status of users for each course on one query, I hope that makes sense?!?
Try:
SELECT c.course_name,
COUNT(DISTINCT ug.user_id) AS "Enrolled",
COUNT(DISTINCT ch.user_id) as "Started"
FROM courses c
left join usergroups ug on ug.course_id = c.id
left join coursehits ch on ch.course_id = c.id and ch.page_id != 4
GROUP BY c.course_name