Reputation: 1369
SURVEYS
table:SurveyID
UserID
Question
Choice1
Choice2
Choice3
RESPONSES
table:UserID
SurveyID
Answer
The first desire (achieved): Show me all surveys that User 28 has initiated:
SELECT *
FROM Surveys
WHERE Surveys.UserID = 28
The second desire (achieved): Show me all surveys that User 28 has answered:
SELECT *
FROM Surveys
INNER JOIN Responses ON Surveys.SurveyID = Responses.SurveyID
WHERE Responses.UserID = 28
Show me all surveys that were NOT initiated by User 28 and which User 28 has NOT already answered... SELECT * FROM Surveys INNER JOIN Responses ON Surveys.SurveyID = Responses.SurveyID WHERE Surveys.UserID <> 28 AND Responses.UserID <> 28 [alternately: WHERE NOT Surveys.UserID = 28 OR Responses.UserID = 28]
The third query eliminates a record for User 28 but other instances of the same survey will appear. For instance, let's say that User 29 answered the survey. A row would be returned because the WHERE doesn't prohibit User 29's record.
I thought of using a subquery -- something like: SELECT * FROM Surveys WHERE Surveys.UserID <> 28 AND Surveys.SurveyID <> (SELECT Responses.SurveyID WHERE Responses.UserID = 28) -- but that doesn't work because the sub-query can easily produce more than one row.
What's the solution?
Upvotes: 2
Views: 940
Reputation: 4060
Something like this I think should do?
SELECT *
FROM Surveys s
WHERE s.UserID != 28
AND s.SurveyID NOT IN (SELECT R.SurveyID FROM Responses R WHERE R.UserID = 28)
Upvotes: 0
Reputation: 332571
SELECT s.*
FROM SURVEYS s
WHERE s.userid != 28
AND s.surveyid NOT IN (SELECT r.survey_id
FROM RESPONSES r
WHERE r.userid = 28)
SELECT s.*
FROM SURVEYS s
LEFT JOIN RESPONSES r ON r.survey_id = s.surveyid
AND r.user_id = 28
WHERE s.userid != 28
AND r.userid IS NULL
SELECT s.*
FROM SURVEYS s
WHERE s.userid != 28
AND NOT EXISTS (SELECT NULL
FROM RESPONSES r
WHERE r.userid = 28
AND r.survey_id = s.surveyid)
Of the options listed, the NOT IN
and LEFT JOIN/IS NULL
are equivalent though I prefer the NOT IN
because it is more readable.
Upvotes: 6