I have the following MySQL tables:
tbl_pet_owners:
+----+--------+----------+--------+--------------+
| id | name | pet | city | date_adopted |
Then perform a RIGHT JOIN instead of LEFT JOIN saying
RIGHT JOIN tbl_pet_types types ON owners.pet = types.pet
In case you want outer joined result for both table (which not sure off), you can then consider doing a FULL JOIN by mixing right and left join
Does MySQL STILL not have CTEs? They make life so much easier.
Regardless, to get 'NOT FOUND', use coalesce() in your SELECT.
SELECT DISTINCT p.petType
, coalesce(po.name,'NOT FOUND') AS name
, coalesce(po.city,'NOT FOUND') AS city
FROM (
SELECT 'mammal' AS petType UNION ALL
SELECT 'fish' UNION ALL
SELECT 'amphibian' UNION ALL
SELECT 'seacreature'
) p
LEFT OUTER JOIN (
SELECT tpo.name, tpo.city, pt.type AS petType
FROM tbl_pet_owners tpo
LEFT OUTER JOIN tbl_pet_types tpt ON tpo.pet = tpt.pet
) po ON p.petType = po.petType
I don't have a MySQL machine to test this on, but something like this should give you what you're looking for.
A left join is correct, but you need for the types to be first:
SELECT DISTINCT types.type, owners.name, owners.city
FROM tbl_pet_types types LEFT JOIN
tbl_pet_owners owners
ON owners.pet = types.pet
WHERE types.type IN ('mammal', 'fish', 'amphibian', 'seacreature');
Because the WHERE clause refers only to tbl_pet_types, it does not change.
How left join works is simple: It keeps all rows in the first table. Unmatched columns in the second become NULL.
EDIT:
If you have a list of types that are not in tbl_pet_types, then you need a left join with all the values in a derived table:
SELECT DISTINCT tt.type, po.name, po.city
FROM (SELECT 'mammal' as type UNION ALL
SELECT 'fish' as type UNION ALL
SELECT 'amphibian' as type UNION ALL
SELECT 'seacreature' as type
) tt left join
tbl_pet_types pt
ON pt.type = tt.type LEFT JOIN
tbl_pet_owners po
ON po.pet = pt.pet;