MySql - apply limit to joined rows only - mysql

Consider the following query:
SELECT u.id
, u.name
, p.id
FROM users u
LEFT
JOIN posts p
ON p.id IN(
SELECT x.id
FROM posts x
WHERE x.user_id = u.id
ORDER
BY x.featured DESC
LIMIT 10
);
I am trying to join the posts table to the users table. However I only want to retrieve a maximum of 10 posts per user.
This approach throws the following error:
This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
Is there an alternative approach to achieve the desired result?

You should use an inner join on subquery instead of left join and IN clause
SELECT users.id, users.name, t.id
FROM users
INNER JOIN (
SELECT posts.id, posts.user_id
FROM posts
WHERE posts.user_id = users.id
ORDER BY posts.featured DESC
LIMIT 10 ) t on t.user_id = users.id
In this way you don't use a limit inside a In clause for subquery and this should not raise the error .. the error for both LIMIT & IN .... but not for athe sue of in limit in subquery in JOIN (withou IN clause)

Related

Retrieve last 10 results ASC Left Join MySql

I'm trying to retrieve the last 10 posts from a posts table ordered ASC, but the last left joined query doesn't retrieve anything.
Basic: it retrieves results ordered DESC
SELECT
p.post, p.id_post, u.name
FROM
posts p
LEFT JOIN
users u ON u.id_user = p.id_user
WHERE
p.id_user = 4
ORDER BY
p.date DESC
LIMIT 10
Ordered ASC: it doesn't work at all:
SELECT
num.*
FROM
(SELECT
p.post, p.id_post, u.name
FROM
posts p
LEFT JOIN
users u ON u.id_user = p.id_user
WHERE
p.id_user = 4
ORDER BY
p.date DESC
LIMIT 10) num
ORDER BY
p.date ASC
What am I doing wrong?
In my php variables I use $row['id_post'] $row['post'] $row['name']. I don't want to use array_reverse() just plain sql
You need to return the date in the subquery:
SELECT pu.post, pu.id_post, pu.name
FROM (SELECT p.*, u.name
FROM posts p LEFT JOIN
users u
ON u.id_user = p.id_user
WHERE p.id_user = 4
ORDER BY p.date DESC
LIMIT 10
) pu
ORDER BY pu.date ASC;
Your second query should have returned an error message to the effect that date is not recognized as a column. You should be capturing and reading error messages, if you want to write an effective application.

Join two different tables ordered by common value (hotness)

I'm trying to select results from two different unrelated tables, showcase and questions to appear in a feed. They should be ordered by the common column hotness which is a float value.
SELECT s.id,s.date,s.title,s.views,s.image,s.hidpi,s.width,s.description,u.display_name,u.avatar
FROM showcase AS s
INNER JOIN users AS u ON s.user_id = u.id
UNION
SELECT q.id,q.date,q.title,q.views,q.text,u.display_name,u.avatar,0,0,0
FROM questions AS q
INNER JOIN users AS u ON q.user_id = u.id
ORDER BY hotness DESC
LIMIT 10
I've tried UNION, but I have no idea how I should be using it here and get this error unknown column hotness
You need to select the value in order for the ORDER BY to recognize it:
SELECT s.id,s.date,s.title,s.views,s.image,s.hidpi,s.width,s.description,u.display_name,u.avatar, s.hotness
FROM showcase AS s
INNER JOIN users AS u ON s.user_id = u.id
UNION ALL
SELECT q.id,q.date,q.title,q.views,q.text,u.display_name,u.avatar,0,0,0, q.hotness
FROM questions AS q
INNER JOIN users AS u ON q.user_id = u.id
ORDER BY hotness DESC;
Note that I also changed the UNION to UNION ALL. Unless you intend to remove duplicates, there is no reason to incur the extra processing for doing that.
You can try this query:
SELECT r.* FROM (
SELECT s.id,s.date,s.title,s.views,s.image,s.hidpi,s.width,s.description,u.display_name,u.avatar, s.hotness
FROM showcase AS s
INNER JOIN users AS u ON s.user_id = u.id
UNION
SELECT q.id,q.date,q.title,q.views,q.text,u.display_name,u.avatar,0,0,0, q.hotness
FROM questions AS q
INNER JOIN users AS u ON q.user_id = u.id
) as r
ORDER BY r.hotness DESC
LIMIT 10
You need to merge Union result in subquery to apply Order by on the result. I also added hotness in select clause, please check I take field from good table.

MySQL subquery with LIMIT alternative

What I want:
SELECT u.username, u.last_activity
FROM users_userprofile
WHERE u.id IN (
SELECT DISTINCT(p.user_id) FROM forums_post p
WHERE p.thread_id = 423993
ORDER BY p.created_at DESC
LIMIT 4
);
This doesn't work because of LIMIT in subquery. I want to keep order of subquery but I want to get username and last_activity instead of user_id.
Any suggestion how I could achieve this?
Replace the subquery with a view:
CREATE VIEW subv AS SELECT p.user_id FROM forums_post p
WHERE p.thread_id = 423993
ORDER BY p.created_at DESC
LIMIT 4;
SELECT u.username, u.last_activity
FROM users_userprofile
WHERE u.id IN (SELECT * FROM subv);
you could use join for the table and the subquery instead of using where in:
SELECT u.username, u.last_activity
FROM users_userprofile u
JOIN (
SELECT p.user_id FROM forums_post p
WHERE p.thread_id = 423993
ORDER BY p.created_at DESC
LIMIT 4
) q
on u.user_id=q.user_id
Why woldn't you do it with a JOIN? There seems to be no performance impact because WHERE and LIMIT clauses are the same. It won't JOIN the whole tables:
SELECT p.user_id, u.username, u.last_activity
FROM users_userprofile u
JOIN forums_post p ON p.user_id = u.id
WHERE p.thread_id = 423993
GROUP BY p.user_id ORDER BY MAX(p.created_at) DESC
LIMIT 4

Load three posts by user

I am looking to load all posts, sorted by newest first, but also limit them to three per user. I have no idea how to do that though! Here's the SQL I have currently to create the table and select the posts.
SELECT p.title, u.firstname, u.lastname
FROM post p
JOIN user u
ON p.user_id=u.id
ORDER
BY u.id, p.ctime DESC
#LIMIT TO 3 by user
;
This is what you can do
select
u.*,
p.*
from
user u
left join
(
select
p1.*
FROM
post p1
where
(
select
count(*)
from
post p2
WHERE
p1.user_id = p2.user_id
AND p1.id <= p2.id
) <= 3
order by p1.id desc
) p ON u.id = p.user_id
order by u.id
Took help from MySQL Limit LEFT JOIN Subquery after joining
Something like this might work
SELECT u.*,up.* FROM user u LEFT JOIN
(
SELECT `p`.`title`, `u`.`firstname`, `u`.`lastname`
FROM `post` `p`
ORDER
BY `p`.`ctime` DESC
LIMIT 3
)
up on up.user_id = u.id

Mysql Nested/Multiple Query handling

I have three queries gives me result individually correct but my requirement is i need all result in single query only so how should i proceed?
select * from user_post_like
inner join user_post on user_post_like.postID = user_post.postID
inner join Users on Users.userID=user_post_like.userID
where (user_post.poster='$uid' AND user_post_like.userID!='$uid')
ORDER BY likeID DESC;
select * from user_post_comment
inner join user_post on user_post_comment.postID = user_post.postID
inner join Users on Users.userID=user_post_comment.commenter
where (user_post.poster='$uid' AND user_post_comment.commenter!='$uid')
ORDER BY commentID DESC;
select * from user_post_share
inner join user_post on user_post_share.postID = user_post.postID
inner join Users on Users.userID=user_post_share.Share_user_id
where (user_post.poster='$uid' AND user_post_share.Share_user_id!='$uid')
ORDER BY shareID DESC;
Since you're joining the tables anyway, you can put columns from all in your select - and keep your statement readable. If you have duplicate column names (from different tables) you may need to aggregate them with functions and group by.
SELECT s.*, p.*, u.*
FROM user_post_share s
INNER JOIN user_post p ON s.postID = p.postID
INNER JOIN Users u ON u.userID = p.poster
WHERE (p.poster='$uid' AND s.Share_user_id != '$uid')
ORDER BY shareID DESC
try sumthing like this
select * from user_post_like,user_post_comment,user_post_share <inner joins> <where conditions>