2
\$\begingroup\$

I've the following tables

Candidates
Id Name PicId
 1 Tom NULL
 2 James 1
 3 Bob NULL
 4 Manny 2
Attachments
Id Name
 1 One.jpg
 2 Two.doc
 3 Three.rtf
The join table AttachmentCandidate
CandidateId AttachmentId
 3 1
 3 2
 4 3

So from the above tables it shows that a candidate's 'PicId' is nullable & one candidate can have 0 or many attachments.

Now the query what I wish to create is the one which should return me Candidate's Name, PicId, & Attachment Name, but I don't want the candidates who neither have a PicId nor any Attachments.

I was able to achieve it with a subquery. Is there any better way it can be done??

SELECT r.cname,r.picId,r.attName FROM 
(SELECT Candidates.Name as cname,
Candidates.PicId as picId, 
Attachments.Name as attName
FROM Candidates LEFT JOIN AttachmentCandidate
ON Candidates.Id = AttachmentCandidate.CandidateId
LEFT JOIN Attachments
ON AttachmentCandidate.AttachmentId = Attachments.Id) as r
WHERE (r.picId IS NOT NULL OR r.attName IS NOT NULL)
Result
cname picId attName
James 1 NULL
Bob NULL One.jpg
Bob NULL Two.doc
Manny 3 Three.rtf

And the candidate 'Tom' not is present in the result since he doesn't have a picId nor any attachments

asked Sep 23, 2015 at 15:41
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

My only real comment to make is that the subquery is irrelevant. You can achieve the same result without it.


When specifying your column aliases in the outer query. There is no need for you to use AS picid as the column is already called picid.


You could also use table aliases as well to shorten some of the statements. I personally prefer to see aliases than fully qualified table names. Assuming everyone sticks to a naming convention of course. My normal rule of thumb is that each capital letter of the table becomes the alias.


Also, as we can remove the subquery, we can change the WHERE clause so it is no longer filtering out the attachment name but instead the PK (WHERE a.Id IS NOT NULL).


For the columns being returned, can we make them more explicit? i.e. CandidateName instead of CName, etc.

Here is the modified version of your query using the changes above:

SELECT
 c.Name AS CandidateName
 ,c.picid AS PicId
 ,a.Name AS AttachmentName
FROM Candidates c
LEFT JOIN AttachmentCandidate ac ON c.Id = ac.CandidateId
LEFT JOIN Attachments a ON ac.AttachmentId = a.Id
WHERE c.picid IS NOT NULL
OR a.Id IS NOT NULL

I'm not sure whether the formatting is just bad when you created your question or whether your SQL query is like that? If so, it's badly formatted and difficult to read. I try and break up each part of the query into separate segments so it's easy to read and maintain by others:

SELECT
 r.cname
 ,r.PicId
 ,r.attName
FROM
(
 SELECT
 Candidates.Name AS cname
 ,Candidates.PicId AS picid
 ,Attachments.Name AS attname
 FROM Candidates
 LEFT JOIN AttachmentCandidate ON Candidates.Id = AttachmentCandidate.CandidateId
 LEFT JOIN Attachments ON AttachmentCandidate.AttachmentId = Attachments.Id
) AS r
WHERE (r.PicId IS NOT NULL OR r.attName IS NOT NULL)

As you requested an alternative, i'll give you one. Essentially it's pretty much the reverse of what you're doing. I'm gathering all of the candidates with attachments first and then I RIGHT JOIN back onto the candidates table and filter out the ones without a PicId.

SELECT
 c.Name AS CandidateName
 ,c.PicId AS PicId
 ,a.Name AS AttachmentName
FROM AttachmentCandidate ac
INNER JOIN Attachments a ON a.Id = ac.AttachmentId
RIGHT JOIN Candidates c ON c.Id = ac.CandidateId
WHERE c.picid IS NOT NULL
OR a.Id IS NOT NULL
answered Oct 1, 2015 at 20:05
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.