I am having trouble trying to create a query to:
Select all the students who have not completed all peer review's for a particular week.
background: Each week, every student must peer review their peers in the same group.
Each group can be a different size, which is the problem I am having.
this is my current test data:
Table 1: peer review table
Table 2: student table.
This is my inital query, groups all the students based on the amount of peer review's they've made. I now need to to check if the count(*) is less than the size of the group for each student :
SELECT *
FROM peerreview
RIGHT JOIN student
ON student. studentID = peerreview.reviewer
WHERE week = 11
GROUP BY studentID
HAVING Count(*) < ????
Following query will return the student which has reviewed all the students in same group.
SELECT a.reviewer,
a.groupid
FROM (SELECT student2.studentID AS reviewer,
student1.groupid,
Count(*) AS cnt
FROM student student1
INNER JOIN peerreview
ON student1.studentID = peerreview.reviewee
INNER JOIN STUDENT STUDENT2
ON student2.studentID = peerreview.reviewer
WHERE student2.groupid = student2.groupid
AND peerreview.week = 11
GROUP BY student1.groupid,
student2.studentID) a
INNER JOIN (SELECT groupid,
Count(*) - 1 AS cnt
FROM student
GROUP BY groupid) b
ON a.groupid = b.groupid
AND a.cnt = b.cnt
See SqlFiddle
Select S.StudentId As Reviewer
, S1.StudentId As StudentYetToBeReviewed
, Weeks.WeekNum
From Student As S
Join Student As S1
On S1.GroupId = S.GroupId
And S1.StudentId <> S.StudentId
Cross Join (
Select 7 As WeekNum
Union All Select 11
) As Weeks
Where Not Exists (
Select 1
From PeerReview As P1
Where P1.reviewee = S1.StudentId
And P1.Week = Weeks.WeekNum
)
Order By WeekNum, reviewer
This provides you a list, by week, of the reviewer and the person they need to review. In the real solution, you would want to replace the Cross Join of weeks with a distinct list of weeks in which reviews should happen.
SQL Fiddle version
select distinct s1.*
from student s1 inner join student s2 on s1.groupId = s2.groupeId
left join peerreview pr on pr.revieweer = s1.studentId
and pr.reviewee = s2.studentId
where pr.Week = ? and pr.revieweer is null and s1.studentId <> s2.studentId
Related
[DB Table]
SELECT b.first_name, b.last_name, a.pod_name, a.category, c.user_id,
SUM(IF(QUARTER(CURDATE())-1 OR (QUARTER(CURDATE())-2) AND a.user_id, 1, 0)) AS flag FROM kudos a
INNER JOIN users b ON a.user_id = b.id INNER JOIN users_groups c ON a.user_id = c.user_id
INNER JOIN groups d ON c.group_id = d.id WHERE a.group_name = 'G2' AND d.id IN (7,8,9,11,12,13,14,15,16,17,21,22,23,24,25,26,27,28)
AND QUARTER(CURDATE())-1 = a.quarter ORDER BY a.final_score+0 DESC
I need to get the user_ids of those users which are both in quarter 1 and 2 from table.
Tried above query but failed to get expected results.
Can someone please guide me on this?
if you only need user_id then you can do this :
select user_id
from tablename
where quarter in (1,2)
group by user_id
having count(distinct quarter) = 2
another way is to use window function, assuming you have one user id in each quarter:
select * from (
select * , count(*) over (partition by user_id) cn
from tablename
where quarter in (1,2)
) t where cn = 2
Select s.SID , s.Lastname, s.Firstname, s.MI, g.YearLevel, g.Course,
count(s.SID) As 'Number Of Passed Subject'
From student s
inner Join grades g on g.StudentID = s.SID
Where g.Completion = 'Passed' and g.YearLevel = '4th Year'
group by g.YearLevel, g.Course
order by g.YearLevel, g.Course;
Select s1.SID , s1.Lastname, s1.Firstname, s1.MI, g1.YearLevel, g1.Course,
SUM(su.LecUnit) As 'Total of Units Passed'
From grades g1
INNER Join student s1 ON s1.SID = g1.StudentID
INNER Join subjects su ON su.SubjectCode = g1.SubjectCode
WHERE g1.Completion = 'Passed' AND g1.YearLevel = '4th Year'
GROUP BY g1.Course, g1.YearLevel
order by g1.Course, g1.YearLevel;
Use the second query as the starting point, and then add a distinct count of student courses for the number of passed subjects. The logic here is that the additional join to the subjects table might duplicate each intermediate record from the first two joins. Taking the distinct count removes this possible duplication.
Select s1.SID, s1.Lastname, s1.Firstname, s1.MI,
COUNT(DISTINCT g1.Course) As `Number Of Passed Subject`,
SUM(su.LecUnit) As `Total of Units Passed`
FROM student s1
INNER JOIN grades g1 ON s1.SID = g1.StudentID
INNER JOIN subjects su ON su.SubjectCode = g1.SubjectCode
WHERE g1.Completion = 'Passed' AND g1.YearLevel = '4th Year'
GROUP BY 1
ORDER BY 1;
Note that I am also grouping only by s1.SID. Assuming SID be the primary key from that table, it covers all columns from the student table. The other table fields you were selecting probably don't belong there.
There are 3 types of adventures for which I used distinct function in query.
There is only one 1 customer who have booked all types of adventures.
The query i used to fetch the data is:
select c.customerid,c.name
from customer c
inner join booking b
on c.customerid = b.customerid
inner join destination d
on b.destinationid=d.destinationid
inner join adventure a
on d.adventureid=a.adventureid
group by c.customerid
having count(distinct b.bid)=(select count(*) from bid)
or count(distinct a.adventuretype)=(
select count(distinct a.adventuretype)
from adventure
)
You can get the customer ids using aggregation and having:
select b.customerid
from booking b join
destination d
on b.destinationid = d.destinationid join
adventure a
on d.adventureid = a.adventureid
group by b.customerid
having count(distinct a.advtype) = 3;
Or, if you don't want to hardcode the "3", you can use:
having count(distinct a.advtype) = (select count(distinct advtype from adventure)
I'll leave it up to you to add in the customer name (using join, exists, or in).
I have a MySQL query which I want to execute to see who is the employee with the best skill X in a company I work for. To do this I randomly pick a company from my cv_profile (skill_cv_test) and find all users who work there for the same employer. And then I randomly choose a skill I have.
The result should either be zero or a list.
But when testing with PHPMyAdmin I get results where I don't see any row, but the status says there is at least one row.
Here's an example of the message I get: https://imgur.com/bVMH716
I have been trying different structures, even "walling" the query with another query, different joins.
SELECT
DISTINCT(sv.usr_id),
u.first_name AS fn,
u.last_name AS ln,
c.name AS company,
s.name AS skill
FROM
(
SELECT
MAX(last_change) as date,
id,
usr_id,
skill_id
FROM skill_valuations
GROUP BY usr_id, skill_id
ORDER BY date
) sv
LEFT JOIN skill_valuations skv ON skv.last_change = sv.date
INNER JOIN
(
SELECT
DISTINCT(skct.comp_id),
skct.usr_id AS usr_id,
skct.category
FROM skill_cv_test skct
WHERE skct.end_date IS NULL AND skct.comp_id IN (SELECT comp_id FROM (SELECT comp_id FROM skill_cv_test WHERE usr_id = 1 ORDER BY RAND() LIMIT 1) x)
) uqv ON uqv.usr_id = sv.usr_id
INNER JOIN
(
SELECT skill_id
FROM usr_skills
WHERE usr_id = $uid
ORDER BY RAND()
LIMIT 1
) usq ON usq.skill_id = sv.skill_id
LEFT JOIN companies c ON c.id = uqv.comp_id
LEFT JOIN skills s ON s.id = sv.skill_id
LEFT JOIN users u ON u.id = sv.usr_id
As mentioned before, I expect either no results or a result of at least one row.
I have two tables as follows:
==================
StudentsClasses
----------------
ID (Registration ID of the class)
StudentID (ID of student taking class)
ClassID (ID of certain class)
----------------
==================
Students
---------------
ID (ID of student)
Name (Name of student)
GradeLevelID (Grade of student)
---------------
==================
And they are joined by StudentsClasses.StudentID and Students.ID.
I am trying to write a query to return the students with the least classes registered. My query is:
SELECT Students.Name, COUNT(StudentsClasses.StudentID) AS Expr1
FROM StudentsClasses INNER JOIN
Students ON StudentsClasses.StudentID = Students.ID
GROUP BY StudentsClasses.StudentID, Students.Name
ORDER BY Expr1
However, that only returns all the students with at least 1 class in ASC order.
I know the correct answer is 7 students with 0 classes.
How can I modify my query to return only those 7 students with 0 classes.
To enlist those students, that have no classes, instead of INNER JOIN you should be using LEFT JOIN here, to make sure all rows from students table are listed, even though there is no rows in studentclasses for that particular student.
SELECT
s.name, count(sc.id) AS classes
FROM
students s
LEFT JOIN studentsclasses sc ON s.id = sc.studentid
GROUP BY s.name
HAVING count(sc.id) = 0 -- added after comment
ORDER BY count(sc.id);
OR another method (for retrieving only students that have 0 classes):
SELECT
s.name
FROM
students.s
LEFT JOIN studentsclasses sc ON s.id = sc.studentid
WHERE
sc.id IS NULL
This should limit your results to those students having whatever the minimum number of registered classes is (so if the minimum is currently zero, then zero, if it becomes true that the least number of registrations is 3, then it will use 3, etc.)
select s.name,
v.classes
from students s
join (
select s.name,
count(sc.id) as classes
from students s
left join studentsclasses sc
on s.id = sc.studentid
group by s.name
order by count(sc.id)
limit 1
) v
on s.name = v.name
Answers for this question.
How can I modify my query to return only those 7 students with 0 classes.
SELECT
s.name, count(sc.id) AS classes
FROM
students s
LEFT JOIN studentsclasses sc ON s.id = sc.studentid
where (SELECT count(sc.id) FROM
students s
LEFT JOIN studentsclasses sc ON s.id = sc.studentid)=0
GROUP BY s.name
ORDER BY count(sc.id);