问题
I have three tables and want to:
Select
all students from
the first table,
that have at least one connection to the school in district '999' in the second table
and
at least one connection to the teacher with social_number '101'
and
at least one to the teacher with number '103' in the third table.
The tables are connected through the second table.
I created an online sql compiler to show the problem: http://tpcg.io/FIoO79xi
This query works fine and as expected, until I add the third EXISTS
Command where I search for a connection to teacher '103'. Then it doesn't return student A anymore, altough he has a connection to teacher '103'
I found a workaround by adding joins
in the Exists sub-query
:
http://tpcg.io/0sza7t5g
but since my real database tables have many million entries, this would lead to joining the three tables in every row that the sub-query
goes through and this can take very long if it only finds a fitting entry at the end of the table.
I think the problem is here at the sub-query
: WHERE th1.school_id = th.school_id
where I'm trying to find a connection from the third table teacher to the at the beginning joined together table. If I search for a connection to teacher 102 instead of 103, the query works and returns student A:
http://tpcg.io/2tHIEk3V
Because teacher 101 and 102 have the same school_id.
But how can I write that differently so that the query also finds student A when I search for a connection to teacher 101 and 103? Student A has a connection to both, so it should be possible somehow with exists...
Add: I can't use three seperate queries and then use the Intersect
command on them, since I'm translating that SQL
into a JPA
query. JPA
doesn`t know intersect...
回答1:
The 1st condition:
at least one connection to the school in district '999' in the second table
needs a join of student
to school
.
The 2nd and 3rd conditions:
at least one connection to the teacher with social_number '101'
and at least one to the teacher with number '103'
need 2 separate joins of student
to school
and teacher
:
SELECT s.name
FROM student s
INNER JOIN school sc on s.student_id = sc.student_id AND sc.district = 999
INNER JOIN school sc1 on s.student_id = sc1.student_id
INNER JOIN teacher t1 on t1.school_id = sc1.school_id AND t1.social_number = 101
INNER JOIN school sc2 on s.student_id = sc2.student_id
INNER JOIN teacher t2 on t2.school_id = sc2.school_id AND t2.social_number = 103
Note that a condition like social_number in (101, 103)
will not work because it would return results even if only 1 of the conditions was satisfied.
This is why you need 2 joins to school
and teacher
.
Also all the joins must be inner
because you want to satisfy all 3 conditions.
See the demo.
Results:
| name |
| ---- |
| A |
回答2:
You need 2 teacher table joins
SELECT name
FROM student
left JOIN school sc1 on #student.student_id = sc1.student_id
left JOIN teacher th1 on sc1.school_id = th1.school_id and th1.social_number=101
left JOIN teacher th2 on sc1.school_id = th2.school_id and th1.social_number=103
where sc1.district=999
回答3:
Why so complicated ?
`SELECT name
FROM student
LEFT JOIN school sc1 on student.student_id = sc1.student_id
LEFT JOIN teacher th1 on sc1.school_id = th1.school_id
WHERE sc1.district = '999'
AND th1.social_number in('101','103')`
doesn't do the trick ?
回答4:
http://tpcg.io/eGeWjkOf
The whole joining is unnecessary when we ask for a connection between the teacher and the student in an additional WHERE
clause.
The Exists subquery
then looks like this, instead of a Join I use an additional where
to make sure the teacher.school_id is the same as the school.school_id of the school the student goes to:
EXISTS (
SELECT *
FROM teacher th
WHERE th.social_number = '103'
AND th.school_id in (SELECT school_id FROM school WHERE student_id = student.student_id ))
来源:https://stackoverflow.com/questions/60739497/i-need-an-jpa-sql-expert-exists-query-on-an-inner-join-returns-wrong-result