I have these tables:
CREATE TABLE students(
id int NOT NULL PRIMARY KEY,
name VARCHAR(30) NOT NULL
);
CREATE TABLE studentsActivities(
studentId int NOT NULL,
activity VARCHAR(30) NOT NULL,
PRIMARY KEY (studentId, activity),
foreign KEY (studentId) REFERENCES students(id)
);
And I have to return all student names that do either Tennis or Football. However, there was a test case which I could not pass and it was stated like that:
Students with the same name.
I do not know the exact implementation of the test cases, but I suspect it was the situation where student A named Carl does Tennis and student B also named Carl does Football and Carl is showed two times. How could I query that database to get the result like that? I’ve created the demo base to try:
CREATE TABLE students(
id int NOT NULL PRIMARY KEY,
name VARCHAR(30) NOT NULL
);
CREATE TABLE studentsActivities(
studentId int NOT NULL,
activity VARCHAR(30) NOT NULL,
PRIMARY KEY (studentId, activity),
foreign KEY (studentId) REFERENCES students(id)
);
INSERT INTO students
VALUES
(1, "Jeremy"),
(2, "Hannah"),
(3, "Luke"),
(4, "Frank"),
(5, "Sue"),
(6, "Sue"),
(7, "Peter");
INSERT INTO studentsActivities
VALUES
(1, "Tennis"),
(1, "Football"),
(2, "Running"),
(3, "Tennis"),
(4, "Football"),
(5, "Football"),
(6, "Tennis");
SQL Fiddle And let’s suppose that the passing set would be:
Jeremy
Luke
Frank
Sue
Sue
I’ve attempted with these two queries, but none gives the correct answer.
--- 1
SELECT s.name
FROM students s
JOIN studentsActivities sa
ON sa.studentId = s.id
WHERE activity = "Tennis"
UNION
SELECT s.name
FROM students s
JOIN studentsActivities sa
ON sa.studentId = s.id
WHERE activity = "Football"
--- Returns Frank Jeremy Luke Sue (missing one Sue)
--- 2
SELECT s.name
FROM students s
JOIN studentsActivities sa
ON sa.studentId = s.id
WHERE activity = "Tennis"
OR activity = "Football"
ORDER BY s.name;
--- Returns Frank Jeremy Jeremy Luke Sue Sue (too much Jeremies)
Advertisement
Answer
Join the tables, filter only the rows with the activities that you want and return distinct rows:
select distinct s.id, s.name
from students s inner join studentsActivities a
on a.studentId = s.id
where a.activity in ('Tennis', 'Football')
See the demo.
Results:
| id | name |
| --- | ------ |
| 1 | Jeremy |
| 3 | Luke |
| 4 | Frank |
| 5 | Sue |
| 6 | Sue |
If you want only the names of the students without the ids:
select s.name
from students s inner join studentsActivities a
on a.studentId = s.id
where a.activity in ('Tennis', 'Football')
group by s.id, s.name
See the demo.
Results:
| name |
| ------ |
| Jeremy |
| Luke |
| Frank |
| Sue |
| Sue |