I want to write a query that displays photos that user 5 did not like. Photos and likes are 2 tables joined by Photo_Id / Image_Id.
To display photos that user 5 did like I write:
Select
wp_photos.Photo_Id
From
wp_photos inner Join
wp_photos_likes On wp_photos.Photo_Id = wp_photos_likes.Image_Id
Where
wp_photos_likes.From_Id = 5
Group By
wp_photos.Photo_Id
I would like a query that displays all photos that user 5 (From_Id) did not like.
Trying
Where
wp_photos_likes.From_Id <> 5
Does not work as other users liked photos that user 5 liked and so returns these as well.
I tried some left joins but with no success.
What's the correct query?
You can use a left join antipattern:
select p.photo_id
from wp_photos p
left join wp_photos_likes l
on p.photo_id = l.image_id and l.from_id = 5
where l.image_id is null
This phrases as: check if each photo was liked by user 5, and filter on thoses who were not.
Another way to solve this is to use a not exists condition with a correlated subquery:
select p.photo_id
from wp_photos p
where not exists (
select 1
from wp_photos_likes l
where p.photo_id = l.image_id and l.from_id = 5
)
Related
I have three tables and Im trying to count the number of likes per user on all his/her post.
USER TABLE
id name
1 John
2 Joe
POSTS TABLE
id user_id post_title
1 1 Some Title
2 1 Another Title
3 2 Yeah Title
LIKES TABLE
id post_id
1 1
2 1
3 1
4 2
5 3
My expected output is
ID LIKES
1 4
2 1
Im kinda stuck with the code below. I don't know how to add and count the likes table.
SELECT *
FROM user
INNER JOIN posts
ON user.id = posts.user_id;
You need to extend the join to the LIKES table and then use GROUP BY to group by the user ID and COUNT() all of the records for that user...
SELECT user.id, COUNT(likes.id)
FROM user
INNER JOIN posts ON user.id = posts.user_id
INNER JOIN likes ON posts.id = likes.post_id
GROUP BY user.id
If you want to list people who don't have posts or likes, then you should use outer joins (so change INNER JOIN to LEFT JOIN) so that these users show up.
For your desired result, you don't need the user table. You can simply do:
SELECT p.user_id, COUNT(*)
FROM posts p JOIN
likes l
ON l.post_id = p.id
GROUP BY p.user_id;
The only information you are taking from users is the id, which is already in posts. This assumes that all the user_id values in posts are valid, but that seems like a very reasonable assumption.
I want to retrieve variants of the same article which are part of the same group. DBM is MySQL 5.7.
There are 2 tables:
articles
articles_group
Table articles has the fields:
article_id | title
1 first product
2 second prod
3 3rd prod
4 4th example
Table articles_groups:
group_id | article_id
1 1
1 2
1 3
2 4
In this example I would like to retrieve all other articles which are in the same group as article 1. So that would be article 2 and 3.
My best shot, but somehow pretty complex:
SELECT
art.article_id,
model
FROM
articles art
INNER JOIN
articles_group art_g ON art.article_id = art_g.article_id
WHERE art_g.group_id = (
SELECT ag.group_id
FROM articles a
INNER JOIN articles_group ag ON a.article_id = ag.article_id
WHERE a.article_id = 1
)
How can I retrieve all other articles which belong to the same group of given article in an easy way? I can still change the shema if there is a better setup.
Let's say your given article is 1. To get all articles in same group of given article, you can use subquery to get group_id of given article. Then use outer query to get all articles in same group.
SELECT a.article_id, a.title
FROM articles a
JOIN articles_groups g ON a.ref_id = g.ref_id
WHERE g.group_id = (
SELECT g.group_id
FROM articles a
JOIN articles_groups g ON a.ref_id = g.ref_id
WHERE a.article_id = '1'
)
I have a table called reviews. I get the most current user reviews like this:
SELECT b.item, b.item_id, a.review_id, a.review, c.category, u.username, c.cat_id
FROM reviews a
INNER JOIN items b
ON a.item_id = b.item_id
INNER JOIN master_cat c
ON c.cat_id = b.cat_id
INNER JOIN users AS u
ON u.user_id = a.user_id
ORDER BY a.review_id DESC;
What I want to do is slightly alter it to be more personable for users.
I have another table of user "connections". Kind of like Twitter. When a user follows someone, it gets logged in this table called profile_follow. This has three columns. id, user_id, follow_id. Simply: If I am user #1, and I "follow" user # 3 and user #5, two rows will be added in this table:
profile_follow
------------------------
id | user_id | follow_id
| 1 | 3
| 1 | 5
Here is how I want to change the query above. I want to only show newest reviews, from people you follow.
So I will need at least one more join, for table profile_follow. And I need to pass in a user_id (it's a php function), doing something like `WHERE profile_follow.user_id = '{$user_id}'. I think I will have to add a sub query on this, not use.
Can someone show me how to finish this query? I am not sure how to handle it from here? All of my attempts have been off so far.
I think I need to do something like:
Selectfollow_idwhereuser_id= (logged in user)
And then in the main query:
Select reviews only with profile_follow.follow_id = review.user_id.
I can't figure out how to make this filter work.
Always difficult without testing, but:
SELECT b.item, b.item_id, a.review_id, a.review, c.category, u.username, c.cat_id
FROM reviews a
INNER JOIN items b
ON a.item_id = b.item_id
INNER JOIN master_cat c
ON c.cat_id = b.cat_id
INNER JOIN profile_follow pf
ON pf.follow_id = a.user_id
WHERE profile_follow.user_id = '{$user_id}'
ORDER BY a.review_id DESC;
I have a table - comments. Users can post if not a member of the site but want to show their details if they are.
So if a user comments who is NOT a member I show their posts but don't link to their profile, because they don't have one.
So, in the following query I want to return the rows even if there is no join:
select wc.comment, wc.comment_by_name, wc.user_id, u.url from comments wc
join users u on wc.wag_uid = u.user_id
where id = '1237' group by wc.comment order by wc.dateadded desc
I want to return:
comment comment_by_name user_id url
------- --------------- ------- ----
hello dan 12 /dan
hey jane /jane
world jack 10 /jack
But the above does not return the data for jane as she does not have a user_id
Is there a way to return all data even if the join is null?
use LEFT JOIN instead
SELECT wc.comment, wc.comment_by_name, wc.user_id, u.url
FROM comments wc
LEFT JOIN users u
on wc.wag_uid = u.user_id
WHERE id = '1237'
GROUP BY wc.comment
ORDER BY wc.dateadded DESC
basically INNER JOIN only select records which a record from one table has atleast one match on the other table while LEFT JOIN select all rows from the left hand side table (in your case, it's comments) whether it has no match on the other table.
Scenario:
We have 5 users. (users table)
Each user has up to 10 imgs. (image table)
These 10 images can be ordered 1 – 10. (image table)
Each img can be listed in multiple categories (say there are 5 categories – birds, bees, bunnies, brains, belugas (category table connected to img table via table that stores img_ids and category_ids)
In searching through the categories, say someone chooses bees. The search should find the images in that category that is listed CLOSEST to the #1 img for all users. So if each user has 3 images in the bees category, ordered as numbers 4, 7 & 9, the search should show the 4th as its closest to the number 1.
The results I keep getting are all over the place and almost seems like it is choosing the images via WHEN they were added to the DB.
SELECT i.img_name, i.ordered, a.user_name, c.keyword, c.cat_id
FROM images AS i JOIN artists AS a USING (user_id)
JOIN img_cat_table AS im USING ( img_id )
JOIN catkeys AS c USING (cat_id)
WHERE ( cat_id = 3) // THE BEES ID #
GROUP BY user_id ORDER BY user_name DESC
I'm also not sure if you want to show all of the relevant images in the right order, or only the top one. Assuming that it is the latter situation, you will need to join to a subquery or view that returns the min rank for each user, category:
SELECT i.img_name, i.ordered, a.user_name, c.keyword, c.cat_id
FROM images AS i JOIN artists AS a USING (user_id)
JOIN img_cat_table AS im USING ( img_id )
JOIN catkeys AS c USING (cat_id)
JOIN (
SELECT user_id, min(img_rank) img_rank
FROM images AS i
JOIN artists AS a on i.user_id = a.user_id
JOIN img_cat_table AS im on im.img_id = i.img_id
JOIN catkeys AS c on c.cat_id = i.cat_id
WHERE ( cat_id = 3) ) x on x.user_id = a.user_id and x.img_rank = img_rank
WHERE c.cat_id = 3
I'm not sure what the name of the column that holds the image ranking is. I called it img_rank. Hopefully this will give you the idea
though if you can post the table structure and data, that will be great but Here is what I haved tried
SELECT i.img_name, i.ordered, a.user_name, c.keyword, c.cat_id
from (
select img_name, ordered, img_id, user_id from
images
group by user_id
order by user_img ) as i
JOIN artists AS a USING (user_id)
JOIN img_cat_table AS im USING ( img_id )
JOIN catkeys AS c USING (cat_id)
WHERE ( cat_id = 3) // THE BEES ID #
Try removing DESC from your ORDER BY clause.