Using an else in an SQL query - mysql

I have the following query in which joins a couple of tables. One of those tables is profile_img. This table houses profile images for users who have uploaded them, otherwise they are given profile_images/default.jpg and the user is not in the profile_img table, so I need a case of sorts to check if they aren't in that table and then to set their profile image as the default.
Here is my query.
SELECT f.*, u.*, p.*
FROM friends f
LEFT JOIN
profile_img p
ON p.user_id = f.friend_one
JOIN
users u
ON u.id = f.friend_one
WHERE f.friend_two = ? AND f.status = ? AND
p.id = (select max(p2.id) from profile_img p2 where p2.user_id = p.user_id)
I have tried ,coalesce(p.img, 'profile_images/default.jpg') as img to try and get the result, but it did not help.
In another query:
(case when p.img <> '' then p.img
else 'profile_images/default.jpg'
end) as img
I am just not sure how to get it to work in this case and it does not work for this.

#marekful is correct in the use of ifnull() but there is one other fix thats needed.
In your where clause you are referencing p.id =. Since p will be null when there are no profile_img rows for that user, the whole row will be excluded from the results due to the compare to null.
This query takes into account the null p.id fields and includes them anyway by allowing p.id when its null. Now p.image_url will be null and the ifnull() method will respond with 'default.png' for those rows.
SELECT f.*, u.*, p.*, IFNULL(p.image_url, 'default.png') AS profile_pic
FROM friends f
LEFT JOIN
profile_img p
ON p.user_id = f.friend_one
JOIN
users u
ON u.id = f.friend_one
WHERE
f.friend_two = ?
AND f.status = ?
AND ( p.id is null or p.id = (select max(p2.id) from profile_img p2 where p2.user_id = p.user_id) )
You may also be able to do this without the OR clause by adding the subquery to the ON predicate. The subquery is then resolved before the join.
SELECT f.*, u.*, p.*, IFNULL(p.image_url, 'default.png') AS profile_pic
FROM friends f
JOIN
users u
ON u.id = f.friend_one
LEFT JOIN
profile_img p
ON p.user_id = f.friend_one and p.id = (select max(p2.id) from profile_img p2 where p2.user_id = p.user_id)
WHERE
f.friend_two = ?
AND f.status = ?
I'm not sure which one has better performance. You'll have to try that out for yourself.

You can select a field whose value will be set conditionally, e.g. using IFNULL()
SELECT f.*, u.*, p.*, IFNULL(p.image_url, 'default.png') AS profile_pic
FROM friends f
LEFT JOIN
profile_img p
ON p.user_id = f.friend_one
JOIN
users u
ON u.id = f.friend_one
WHERE f.friend_two = ? AND f.status = ? AND
p.id = (select max(p2.id) from profile_img p2 where p2.user_id = p.user_id)

Related

Mysql query returning too many results

I'm working on a project where I need to check if the user liked the post and then use COUNT() on it, if it gives 0 they haven't if it says 1 they have liked it
I tried using this query
SELECT P.id AS id
, U.username AS username
, P.body AS body
, P.timestamp AS timestamp
, COUNT(L.user_id) AS likes
, COUNT(LD.post_id) AS liked
FROM posts AS P
LEFT JOIN users AS U ON U.id = P.user_id
LEFT JOIN followers AS F ON F.user_id = 'user1'
LEFT JOIN likes AS L ON L.post_id = P.id
LEFT JOIN likes AS LD ON LD.post_id = P.id
AND LD.user_id = 'user1'
WHERE F.following_id = P.user_id
OR P.user_id = 'user1'
GROUP BY P.id
My entrys in my likes table are
UserId|PostId|timestamp
user1 |post1 |time
user2 |post1 |time
My problem is it keeps giving a 2 for the count of LD which shouldn't be possible
*Note: In my code I use :user through PDO I don't actually type the id like that
Edit:
$sql = "SELECT P.id AS id, P.user_id AS userid, U.username AS username, U.name AS name, U.verified AS verified, P.body AS body, P.data AS data, P.timestamp AS timestamp, P.type AS type, P.users AS users, COUNT(L.user_id) AS likes, COUNT(DISTINCT LD.post_id) AS liked FROM posts AS P LEFT JOIN users AS U ON U.id = P.user_id LEFT JOIN followers AS F ON F.user_id = :userid LEFT JOIN likes AS L ON L.post_id = P.id LEFT JOIN likes AS LD ON LD.post_id = P.id AND LD.user_id = :userid WHERE F.following_id = P.user_id OR P.user_id = :userid GROUP BY P.id";
$results = DB::query($sql, array(':userid' => $user_id));
I then loop through the results and format them into json
Can you try adding a DISTINCT keyword on the COUNT function for liked column?
COUNT(DISTINCT LD.post_id) AS liked
Most likely the joins are causing the likes table to be duplicated. Thus, we'll only count the unique posts (by post_id) using DISTINCT.

How to change the type of join based on condition in mysql?

I am trying to do something like this:
SELECT m.id, u.first_name AS otherUser
FROM matches AS m
IF (u.id=m.user2ID)
Inner JOIN users AS u ON u.id = m.user1ID
ELSE
LEFT JOIN users AS u ON u.id = m.user2ID
ENDIF
WHERE m.user1ID=2 OR m.user2ID=2
Now my intention is to change the type of join based on condition. Can i do that? If yes then how?
Update:- What i am trying to achieve here is, change the type of join when a certain condition is true like:
if(a==1){
Then do inner join
}else{
Then do left join
}
If this could be euivalent
SELECT m.id, u.first_name AS otherUser
FROM matches AS m
LEFT JOIN users as u
ON ( (u.id=m.user2ID AND ON u.id = m.user1ID ) OR u.id = m.user2ID )
WHERE m.user1ID=2 OR m.user2ID=2

MySql Join tables based on field value

Is it possible to do something like this:
SELECT
p.*, u.*
FROM
posts AS p
IF(p.status = 1)
LEFT JOIN users AS u
ON u.id = p.user_id
ELSE
LEFT JOIN pusers AS u
ON u.id = p.user_id
WHERE p.id = 10 ;
Based on post status being true/false join users/pusers table
No, but you can do this:
SELECT p.*,
(case when p.status = 1 then u.col1 else pu.col1 end) as col1
FROM posts p LEFT JOIN
users u
ON u.id = p.user_id and p.status = 1 LEFT JOIN
pusers AS pu
ON pu.id = p.user_id and p.status <> 1
WHERE p.id = 10 ;
In other words, you can join both tables and use the values from the table, based on the condition.

SQL Join with MAX().

I have two tables, users and contestants. I'm trying to select the max contestant ID that has a profile picture(which is on the user table)
Heres my terrible SQL:
SELECT u.thumbnail, u.id FROM users AS u
INNER JOIN
(
SELECT c.id, c.user_id FROM contestants AS c
WHERE u.id = c.users_id
AND c.id = (select max(c.id))
) WHERE u.thumbnail IS NOT NULL
The error currently is: #1248 - Every derived table must have its own alias.
This confuses me since Users has an alias of u, and contestants has an alias of c..
What am I doing wrong here? I'm guessing a lot so some help would be really appreciated!
Whenever you are performing a join operation, you are actually joining two table. The subquery you wrote here, for instance, is working as a separate table. Hence, you have to use an alias to this table. That's the reason behind your error message.
Your query:
SELECT u.thumbnail, u.id FROM users AS u
INNER JOIN
(
SELECT c.id, c.user_id FROM contestants AS c
WHERE u.id = c.users_id
AND c.id = (select max(c.id))
) WHERE u.thumbnail IS NOT NULL
It should contain an alias for the subquery:
SELECT c.id, c.user_id FROM contestants AS c
WHERE u.id = c.users_id
AND c.id = (select max(c.id))
Let's say, it's T.
So, your query now becomes:
SELECT u.thumbnail, u.id FROM users AS u
INNER JOIN
(
SELECT c.id, c.user_id FROM contestants AS c
WHERE u.id = c.users_id
AND c.id = (select max(c.id))
) AS T
WHERE u.thumbnail IS NOT NULL
But what you are trying to achieve, can actually be done in a neater way:
SELECT u.thumbnail, u.id, max(c.id),
FROM users as u
LEFT JOIN contestants as c
on u.id = c.user_id
WHERE u.thumbnail IS NOT NULL
Why make all the fuss when you have a better and neater approach at your disposal?
try this:
SELECT u.thumbnail, u.id
FROM users AS u
INNER JOIN
(
SELECT c.id, c.user_id FROM contestants AS c
WHERE u.id = c.users_id
AND c.id = (select max(c.id))
)A
WHERE u.thumbnail IS NOT NULL
i think this should be simple,
SELECT u.thumbnail, u.id
FROM users u
INNER JOIN contestants c
ON u.id = c.users_id
WHERE u.thumbnail IS NOT NULL
ORDER BY c.id DESC
LIMIT 1
This is very simple.
SELECT user.thumbnail, user.id
FROM users user
INNER JOIN contestants cont ON cont.id = cont.users_id
WHERE cont.thumbnail IS NOT NULL
ORDER BY user.id DESC

Duplicate results with mysql query

I've 3 tables to query. I make a select on the first one, depending on the two others. I must have only distinct id from the 1st table, but my query is returning some duplicates... http://sqlfiddle.com/#!2/3e3d6/1
My query:
SELECT p.*
FROM posts p, blogs_subscribed s
WHERE (p.user_id = s.user_id OR p.user_id = 1)
AND p.id NOT IN (
SELECT post_id
FROM posts_unsubscribed u
WHERE u.post_id = p.id
AND u.user_id = p.user_id);
SELECT p.*
FROM posts p, blogs_subscribed s
WHERE (p.user_id = s.user_id OR p.user_id = 1)
AND NOT EXISTS(
SELECT null
FROM posts_unsubscribed u
WHERE u.post_id = p.id
AND u.user_id = p.user_id);
Any idea please?
not entirely sure I understand what you are looking for, but I think this is what you want...
SELECT p.*
FROM posts p, blogs_subscribed s
WHERE (p.user_id = s.user_id OR p.user_id = 1)
AND p.id NOT IN (
SELECT post_id
FROM posts_unsubscribed u
WHERE u.post_id = p.id
AND u.user_id = p.user_id)
GROUP BY p.id;
SELECT p.*
FROM posts p, blogs_subscribed s
WHERE (p.user_id = s.user_id OR p.user_id = 1)
AND NOT EXISTS(
SELECT null
FROM posts_unsubscribed u
WHERE u.post_id = p.id
AND u.user_id = p.user_id)
GROUP BY p.id;