简体   繁体   中英

Where, either or not both clause SQL

I am trying to list students who were enrolled in at least one course in Fall quarter or at least one course in the Spring quarter, but not both. I have tried to go at this from different angles but so far I haven't succeeded with any of them. The code that I feel completes this solution would be the following. Any help is appreciated!

SELECT enrolled.StudentID, student.LastName, student.FirstName
   , enrolled.courseID, enrolled.Quarter  
FROM enrolled 
INNER JOIN student ON enrolled.studentID = student.SID
GROUP BY enrolled.StudentID, student.LastName, student.FirstName
   , enrolled.courseID, enrolled.Quarter
HAVING (count(distinct enrolled.Quarter) = 1)

You could use something along the following lines:

 SELECT 
   enrolled.StudentID, student.LastName, 
   student.FirstName, enrolled.courseID, enrolled.Quarter  
 FROM enrolled
 where StudentID in ( 
     SELECT StudentID 
     FROM enrolled where quarter in ( 'fall', 'spring' )
     group by StudentID
     having count(*) = 1 
   )      

Sorry on my phone so not going to be a complete answer.

I would try

Select [what you want]
From students as s
Outer apply
(
Select distinct sid 
From enrolled as e
Where e.sid =s.sid
And quorter = 1
) as q1
Outer apply
(
 Select distinct sid 
From enrolled as e
Where e.sid =s.sid
And quorter = 2
) as q2
Where
((  q1.sid  is null and q2.sid is not null)
Or 
( q1.sid is not null and q2.sid is null))
And (q1.sid is not null and q2.sid is not null)

I'd do a union query.

select yourfields
from enrolled
where studentid in
(select studentid
from enrolled 
where quarter = 'fall'
minus
select studentid
from enrolled 
where quarter = 'spring')

union all
select yourfields
from enrolled
where studentid in
(select studentid
from enrolled 
where quarter = 'spring'
minus
select studentid
from enrolled 
where quarter = 'fall')

Not entirely sure if MySQL supports the keyword minus. Some db's do, some don't. If not, it might support the keyword except.

Stouny's comment was correct, removing quarter from the group by and using an aggregator in the select will work:

SELECT enrolled.StudentID, student.LastName, student.FirstName, enrolled.courseID, max(enrolled.Quarter) as quarter
FROM enrolled 
INNER JOIN student ON enrolled.studentID = student.SID
GROUP BY enrolled.StudentID, student.LastName, student.FirstName, enrolled.courseID
HAVING count(*) = 1

Another approach that won't scale well if you have lots of quarters to check, but works ok for 2:

SELECT enrolled.StudentID, student.LastName, student.FirstName, coalesce(spring.courseID, fall.courseID), coaleasce(spring.Quarter, fall.quarter)  
FROM students
LEFT OUTER JOIN enrolled as spring ON spring.studentId = students.sid and spring.quarter = 'spring'
LEFT OUTER JOIN enrolled as fall ON fall.studentId = students.sid and fall.quarter = 'fall'
WHERE (spring.courseID != NULL and fall.courseID = NULL) OR (spring.courseID ! NULL and fall.courseID != NULL)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM