I'm having huge difficulty with a 3 table query.
The scenario is that TEAM has many or no MEMBERS, a MEMBER could have many or no TASKS. What I want to get is the number of TASKS for every TEAM. TEAM has its own ID, MEMBER holds this as a FK on TEAM_ID, TASK has MEMBER_ID on the TASK.
I want to get a report of TEAM.NAME, COUNT(Person/Team), Count(Tasks/Team)
I have myself so confused, My thinking was to use an Outer Join on TEAM and MEMBER so I have all the teams with any members they have. From here I'm getting totally confused. If anyone can just point me in the right direction so I have something to work from I'd be so greateful
You want to use count distinct:
MySQL COUNT DISTINCT
select t.name as Team,
count(distinct m.ID) as Member_cnt,
count(distinct t.ID) as Task_cnt
from team t
left join member m
on t.ID= m.TEAM_ID
left join tasks t
on t.MEMBER_ID= m.ID
group by t.name;
I think you can do what you want with aggregation -- and count(distinct):
select t.name,
count(distinct m.memberid) as nummembers,
count(distinct tk.taskid) as numtasks
from team t left join
member m
on t.teamid = j.teamid left join
tasks tk
on tk.memberid = m.memberid
group by t.name;
Try this out :
SELECT Team.name, COUNT(Person.id_person), COUNT(Tasks.id_task)
FROM Team t,
LEFT JOIN Person p on p.team_id = t.id_team
LEFT JOIN Tasks ts on ts.person_id = p.id_person
GROUP BY p.team_id, ts.person_id
Related
SELECT Count(Teams.Name)
, Teams.TeamID
, Teams.Name
FROM Teams, Rosters
WHERE Rosters.TeamID = Teams.TeamID
Is my query so far. I'd like it to print the number of entries of Rosters.TeamID that correspond to Teams.TeamID.
I think the query you want is:
SELECT t.TeamID, t.Name, COUNT(*)
FROM Teams t JOIN
Rosters r
ON r.TeamID = t.TeamID
GROUP BY t.TeamID, t.Name;
Basically, your query is missing the GROUP BY, but you should also learn proper JOIN syntax.
I have 4 tables, three are many to many relationship:
Student(StudID,GroupId,Name,....)
Lesson(LessID,LessonName,Mark)
StudentLesson(StudID,LessID)
and the relationship between student and Group is One to Many
Student(StudID,Name,....)
Group(GroupId,GroupNumber)
What I want is how select Name, LessonName, Mark, GroupNumber
select S.Name, L.LessonName, L.Mark, G.GroupNumber from Student s
join StudentLesson SL on SL.StudId = S.StudId
join Lesson L on SL.LessID = L.LessID
Join Group G on G.GroupId = S.GroupId
I think the error in this line Join Group G on G.GroupId=S.GroupId, because when I omit it, it works between many to many but between one to many it didn't work.
group is a reserved word, so it needs to be quoted. In MySQL, you can use backticks:
select S.Name, L.LessonName, L.Mark, G.GroupNumber
from Student S
join StudentLesson SL on SL.StudId = S.StudId
join Lesson L on SL.LessID = L.LessID
Join `Group` G on G.GroupId = S.GroupId
Based on Comments: the query is fine; you lack data that matches the results you're after.
There are no students with a groupID
There are no students with a groupID matching GROUPID in the group table.
To prove this out you could simply make the last join a LEFT Join provided you have no where clause with limits on Group.
FROM:
select S.Name,L.LessonName,L.Mark,G.GroupNumber from Student s
join StudentLesson SL on SL.StudId=S.StudId
join Lesson L on SL.LessID =L.LessID
Join Group G on G.GroupId=S.GroupId
TO:
SELECT S.Name, L.LessonName, L.Mark, G.GroupNumber
FROM Student s
INNER JOIN StudentLesson SL on SL.StudId=S.StudId
INNER JOIN Lesson L on SL.LessID =L.LessID
LEFT JOIN Group G on G.GroupId=S.GroupId
This will show you all students w/ lessons and groupNumber if the groupID's match; but i'm betting they will all be NULL.
So are you after all students regardless if they have lessons or groups if so your inner joins should be left. If you're only after students that have lessons and belong to groups then they all need to be inner joins. Just depends on what you're after!
Left join will say include all records from the prior data joins, and only those that match from this join (to group in the example)
I'm learnin SQL from a book and i'm trying to do some exercices on join queries.The only problem that i'm facing is that all of my join queries are not working while they seem well
students(student_id,student_names,student_age)
courses_students(course_id,student_id)
courses(course_id,course_schedule,course_room,teacher_id)
teachers(teacher_id,teacher_names)
The query is "which courses have more than 5 students enrolled?"
Here is what i've done :
SELECT course_name,
count
(SELECT count(*)
FROM courses) AS COUNT
FROM students,
courses,
courses_students
WHERE students.student_id=courses_students.student_id,
courses.course_id=courses_students.course_id
AND COUNT > 5
And the other one is what are the names of students enrolled in at least 2 courses scheduled for the same hours
My query :
SELECT student_name,
schedule
FROM students,
courses,
courses_students
WHERE students.student_id=courses_students.student_id,
courses.course_id=courses_students.course_id
AND COUNT > 2
In this inner query:
(SELECT count(*)
FROM courses) AS COUNT
you need to narrow down what is included in the COUNT. As it is, it is selecting all items in the courses table. The inner query does not know about the restrictions in the outer query. Try adding a where clause in this inner query. You might need to add table aliases to uniquely refer to the correct courses table, so there is no ambiguity whether it is referring to the courses table in the inner query or the outer query.
And, as noted in other answers, this is not the best way to structure joins.
In MySQL you are required to define joins explicitly. Unlike Oracle it can't handle joins with sign of =.
SELECT course_name,
count
(SELECT count(*)
FROM courses) AS COUNT
FROM students
INNER JOIN courses on courses.course_id=courses_students.course_id
INNER JOIN courses_students on students.student_id=courses_students.student_id
WHERE COUNT(*) > 2
You need to aggregage by course and then assert the number of students:
SELECT
c.course_name,
COUNT(*) AS cnt
FROM courses c
INNER JOIN courses_students cs
ON c.course_id = cs.course_id
INNER JOIN students s
ON cs.student_id = s.student_id
GROUP BY
c.course_name
HAVING
COUNT(*) > 5;
stackoverflow is actually not a site to do homework, but as you already have given a try to solve the task, here is a solution for question number one:
SELECT cs.course_id
FROM courses_students cs
INNER JOIN students s
ON cs.course_id = s.course_id
GROUP BY cs.course_id
HAVING count(*) > 5
Read about the GROUP BY and HAVING clause - nice way to solve some problems.
Question number 2 could be solved like this:
SELECT student_names
FROM students s
INNER JOIN courses_students cs
ON cs.student_id = s.student_id
INNER JOIN (
SELECT course_id
FROM courses c
GROUP BY course_schedule
HAVING count(*) > 1
) sub
ON sub.course_id = cs.course_id
The INNER JOIN with the subquery is selecting courses which are scheduled at the same time (having the same course_schedule).
As the other tables are "connected" with INNER JOINs, we will finally just have the subset of students which are participating one of those courses.
Above is my table schema. My task is to Write a SQL command to display for each publisher the publisher’s name, the publisher’s location and the
average cost of the books that the publisher sells. I have a mostly working query:
SELECT Publisher.name, Publisher.location,
(SELECT AVG(Book.cost)
FROM (Book
INNER JOIN Publisher
ON Book.publisherName = Publisher.name)
WHERE Book.publisherName = Publisher.name
) bookAverage FROM Book
INNER JOIN Publisher ON Book.publisherName = Publisher.name;
The problem is that this returns the average of all books in the Books table. How can I change this to only return the average cost of the books associated with each publisher?
Here's a fiddle with the schema implemented already:
http://sqlfiddle.com/#!9/7a9909/11/0
SELECT p.name, p.location, AVG(b.Cost) as AverageBookCost
FROM
Publisher p
INNER JOIN book b
ON b.publisherName = p.name
GROUP BY
p.name, p.location
http://sqlfiddle.com/#!9/7a9909/18
Only 1 join, no sub queries, inner selects nothing needed as you are looking for the straight forward aggregate of the join between the tables. Simply specify you GROUP BY clause correctly.
You are close. You just have too many JOINs. For instance, the subquery only needs the correlation clause:
SELECT p.name, p.location,
(SELECT AVG(b.cost)
FROM Book b
WHERE b.publisherName = p.name
) as bookAverage
FROM Publisher p;
If you were to write this as a JOIN, you would properly write it using a LEFT JOIN and GROUP BY:
SELECT p.name, p.location, AVG(b.cost) as bookAverage
FROM Publisher p JOIN
Book b
ON b.publisherName = p.name
GROUP BY p.name, p.location;
SELECT Publisher.name, Publisher.location, costs.avg_cost
FROM Publisher
INNER JOIN (
SELECT AVG(Book.cost) as avg_cost, Book.publisherName
FROM Book
GROUP BY Book.publisherName
) AS costs ON costs.publisherName = Publisher.name;
Complementing the great answer/solution from #Matt you can get Publisher Name, Publisher Location, Nbr of books, Total cost of Books and Avg price per Book easily in one single shot:
SELECT b.publisherName, p.location, COUNT(1) AS total_books,
ROUND(SUM(cost), 2) AS books_total_cost, ROUND(AVG(cost), 2) AS avg_cost_per_book
FROM book b
JOIN publisher p ON p.name = b.publisherName
WHERE 1=1
GROUP BY b.publisherName
ORDER BY b.publisherName
;
I think that the query itself is well self-explanatory but if you have any question, please, be my guest :)
I have two tables: match(id.match, date, home, away) and team(id. team, name). In match home and away are foreign keys to the team id. In my query, I want an output record with date of match, and name of these two teams.
I have tried:
SELECT m.date, m.home, m.away, t.name
FROM `match` m
JOIN team t ON m.home = t.id_team
ORDER BY m.date
But this outputs two records instead of one. Is it possible to do what I want with sql or I should just change the table's design?
I suspect you have a many to one relationship between your tables.
This might work depending on the table values:
SELECT DISTINCT m.date, m.home, m.away, t.name
FROM `match` m JOIN
team t ON m.home = t.id_team
ORDER BY m.date
Ok, i did 'deeper' research and find out the answer. Earlier i just asked wrong question. Thanks everyone for contribution!
Here is the solution:
SELECT m.date, m.home, m.away, t.name AS homename, te.name AS awayname
FROM `match` m
JOIN team t ON m.home = t.id_team
JOIN team te
ON m.away = te.id_team ORDER BY m.date