How to fix this JOIN query? - mysql

I have this query:
SELECT *
FROM people
JOIN pets ON people.id = pets.owner_id;
It returns results for people who have pets. But not all people have pets. I want the query to return all persons from the people table and IF they happen to have pets to return the pets also.
But since pets are optional, how can I make this query return even people with no pets?

Use LEFT JOIN
SELECT *
FROM people
LEFT JOIN pets ON people.id = pets.owner_id;
JOIN Explanation
JOIN in SQL

JOIN default to INNER JOIN
in your case you should use
left join

Related

Easy SQL Query - Aligning foreign keys

I'm taking longer than I expected with an easy Query in MySQL. I think it's gonna be a nested query but I don't see it easily.
I have 3 tables: Users, Comments, and Businesses. Comments have business_id, and user_id as foreign keys.
So I want the result of users.name and comments.review, having the number of the business.
So my First (and wrong) attempt was:
SELECT users.name, users.image, comments.review
FROM reviews JOIN users JOIN businesses
WHERE reviews.user_id=users.id AND reviews.business_id=4;
I want to set that PrimaryKey.user_id is equal to ForeignKey.users.id.
From all of the comments, I want to take these which are from the business_id=4.
It gives me failiure with both 'WHERE' clauses. So not sure if I could fix this with a nested query or maybe with a JOIN clause?
Any help will be appreciated!
Thank you all. [Edited Query]
Try this out and let me know in case of any queries.
select c.name,c.image,a.review
from
comments a
inner join
(select * from buisnesses where buisness_id = 4) b
on a.buisness_id = b.buisness_id
inner join
users c
on a.user_id = c.user_id;
or
select b.name,b.image,a.review
from
comments a
inner join
users b
on a.user_id = b.user_id
where a.buisness_id = 4;
Give this a try:
SELECT
users.name,
users.image,
comments.review
FROM reviews
JOIN users
ON reviews.user_id = users.id
JOIN businesses
ON reviews.business_id = business.business_id
WHERE reviews.business_id=4;
Since you're not using any of the columns from the business table, you could probably drop it from the query:
SELECT
users.name,
users.image,
comments.review
FROM reviews
JOIN users
ON reviews.user_id = users.id
WHERE reviews.business_id=4;

How to best do a SQL left join null check where all must be null?

Suppose I have table Person, who owns many Books, which cover many Subjects.
A Book might not yet have any Subjects assigned to them.
It's easy to query for Persons who own SOME Books that have no Subjects with a left join and a null check. e.g.:
select * from persons p
inner join person_book pb on pb.person_id = p.id
left join book_subject bs on bs.book_id = person_book.book_id
where book_subject.book_id is null;
What is the best way to query for a Person who ONLY owns books with no established subjects?
I know I can find people with books, and people with at least 1 book with subjects, then find the difference. But is there a direct way?
(This would be in MySQL if it makes a difference).
Try:
select p.*
from persons p
inner join person_book pb on pb.person_id = p.id
left join book_subject bs on bs.book_id = person_book.book_id
group by p.id
having count(bs.book_id) = 0

JOIN where CAN be joined, else no join

So, I have this MySQL problem.
I've been looking at LEFT JOIN, INNER JOIN etc. And as I understand LEFT JOIN joins from left and if the right part doesn't exist it's values get set to NULL. And with INNER JOIN if there is no match for the join, an empty set is returned.
As you can see from my previous statement I join different statistics and such for one of the users in the match. But if uid2 isnt friend with uid1 this will give null in my case for all fields in friends.*
How would I do to get all the friends fields if they are friends and no fields from friends if they arent. (I dont want to do a separate statement before to check if they're friends).
This is my previous statemenet:
SELECT matches.*, statistics.*, friends.*, users.username
FROM `matches`
LEFT JOIN statistics ON matches.uid1=statistics.uid
LEFT JOIN users ON matches.uid1=users.uid
LEFT JOIN friends ON matches.uid1=friends.fid AND matches.uid2=friends.uid
WHERE matches.mid IN (269,231,131)
Then you just replace the last LEFT JOIN with an INNER JOIN:
SELECT matches.*, statistics.*, friends.*, users.username
FROM `matches`
LEFT JOIN statistics ON matches.uid1=statistics.uid
LEFT JOIN users ON matches.uid1=users.uid
INNER JOIN friends ON matches.uid1=friends.fid AND matches.uid2=friends.uid
WHERE matches.mid IN (269,231,131);
However, it's not possible to selectively not return the columns from the friends table when they can't be joined.
I ended up with still doing a LEFT JOIN, and then filter the result;
$temp = array_filter($temp, "is_not_null");
function is_not_null($var)
{
return ! is_null($var);
}

Need an alternative to two left joins

Hey guys quick question, I always use left join, but when I left join twice I always get funny results, usually duplicates. I am currently working on a query that Left Joins twice to retrieve the necessary information needed but I was wondering if it were possible to build another select statement in so then I do not need two left joins or two queries or if there were a better way. For example, if I could select the topic.creator in table.topic first AS something, then I could select that variable in users and left join table.scrusersonline. Thanks in advance for any advice.
SELECT * FROM scrusersonline
LEFT JOIN users ON users.id = scrusersonline.id
LEFT JOIN topic ON users.username = topic.creator
WHERE scrusersonline.topic_id = '$topic_id'
The whole point of this query is to check if the topic.creator is online by retrieving his name from table.topic and matching his id in table.users, then checking if he is in table.scrusersonline. It produces duplicate entries unfortunately and is thus inaccurate in my mind.
You use a LEFT JOIN when you want data back regardless. In this case, if the creator is offline, getting no rows back would be a good indication - so remove the LEFT joins and just do regular joins.
SELECT *
FROM scrusersonline AS o
JOIN users AS u ON u.id = o.id
JOIN topic AS t ON u.username = t.creator
WHERE o.topic_id = '$topic_id'
One option is to group your joins thus:
SELECT *
FROM scrusersonline
LEFT JOIN (users ON users.id = scrusersonline.id
JOIN topic ON users.username = topic.creator)
WHERE scrusersonline.topic_id = '$topic_id'
Try:
select * from topic t
left outer join (
users u
inner join scrusersonline o on u.id = o.id
) on t.creator = u.username
If o.id is null, the user is offline.
Would not it be better to match against topic_id in the topics table by moving the condition to the join. I think it will solve your problem, since duplicates come from joining with the topics table:
SELECT * FROM scrusersonline
JOIN users
ON users.id = scrusersonline.id
LEFT JOIN topic
ON scrusersonline.topic_id = '$topic_id'
AND users.username = topic.creator
By the way, LEFT JOIN with users is not required since you seem to search for the intersection between scrusersonline and users

How do you JOIN two MySQL tables where the data is NOT in the other table?

For example, I have a pet table and a lost pets table. I want to get all of the pets that are NOT lost with 1 join and no sub-selects. Is that possible? A typical join only returns results that are in both tables.
You're describing an OUTER JOIN as compared to a standard INNER JOIN. Google or check your documentation - I'm sure you'll find lots of examples. :)
SELECT * FROM pets AS p
LEFT OUTER JOIN lost-pets AS lp
ON p.name = lp.name
WHERE lp.id IS NULL
SELECT PETS.NAME
FROM PETS
LEFT OUTER JOIN LOST_PETS
ON PETS.PET_ID = LOST_PETS.PET_ID
WHERE LOST_PETS.PET_ID IS NULL;
It is possible, yes, say :
SELECT *
FROM pets LEFT OUTER JOIN pets-lost ON pets.id = pets-lost.id
WHERE pets-lost.id IS NULL;
Why not do where not exists (select * from Lost ...)? Its a sub-select, but I don't see why thats a problem.