Or at least it’s complex for me, as I’m a total noob with SQL.
I’d like to write a query for my MySQL-ODBC phonebook program, that returns certain details of a person and his primary phone number if there’s one.
Persons and numbers are stored in different tables (persons and numbers), while their relations are in the npr (number-person relations) table.
The primary key of ‘persons’ is ‘nick’, for ‘numbers’ it’s ‘number’, for ‘npr’ it’s ‘persons_nick’ and ‘numbers_number’ together.
If a number is primary, it’s signalled by the word “primary” being somewhere in the type attribute of the npr table. (I know it’s primitive, but I didn’t think I’d need this attribute and now I don’t have time to implement it properly)
Here’s the code as it is now:
SELECT persons.nick AS nick, persons.fullname AS fullname,
persons.prefix AS prefix, persons.surname AS surname,
persons.forename AS forename, persons.photo AS photo,
numbers.prettynumber AS primarynumber
FROM persons
RIGHT JOIN npr ON npr.persons_nick=persons.nick
LEFT JOIN numbers ON npr.numbers_number=numbers.number
WHERE npr.type LIKE '%primary%'
ORDER BY nick;
This, of course doesn’t return anything if the person doesn’t have a primary phone number. How could I rewrite this query to return the person’s attributes and a void number in that case?
Thank you.
The solution for your problem is to move the LIKE constraint into the predicate of the left join:
The WHERE predicate filters all records but the join predicate belongs only to this left join. If the right side doesn’t match, then you still get the left side of the join.
Update
It seems to me that it would be better to only use left joins in this case. I don’t know the exact table definitions, but I assume that table npr is only for the tagged association between persons and numbers. So if you use only left joins then you can be sure, you get all persons whether or not they have a primary number.