mysql select top users problem - mysql

i have users table and i have posts table i want select from users the top users that have the big amount of posts from posts table and order them by numbers of posts
i can make it by array_count_values() by i cant order it
now i think if i make it by one mysql query by left and join will be more better
table structure
posts
id | auther_id
i tried this
SELECT COUNT(1) cnt, u.user_id
FROM users u
LEFT JOIN posts p
ON p.author_id=u.user_id
GROUP BY u.user_id
ORDER BY cnt DESC
LIMIT 20
it gave me this
alt text http://img511.imageshack.us/img511/6707/31154352.gif
see the arrow
what is this
i just have 2 posts under user_id 5
what is this first row

You need to aggregate the posts by user using GROUP BY u.user_id, get a COUNT value for the number of posts and ORDER BY that number, in descending order:
SELECT COUNT(1) cnt, u.user_id
FROM users u
LEFT JOIN posts p
ON p.author_id=u.user_id
GROUP BY u.user_id
ORDER BY cnt DESC
LIMIT 20

SELECT u.user_id, COUNT(*) as post_count
FROM users u
INNER JOIN posts p
USING (user_id)
GROUP BY u.user_id
ORDER BY post_count

i used this and its worked
is it true
SELECT COUNT( 1 ) cnt, a.auther_id
FROM `posts` a
LEFT JOIN users u ON a.auther_id = u.id
GROUP BY a.auther_id
ORDER BY cnt DESC
LIMIT 20

Related

How to write a query that retrieves 3 replies for each user in my users table?

i want to display three replies from each user i have in my users table, so for instance if i have 3 users and each of them had replied to lets say 10 messages, i want my query to only retrieve 9 replies and not all of the replies in my messages_reply table.
heres what i tried:
$replyquery="select *
from messages_reply
LEFT JOIN users
ON messages_reply.from_id=users.id
GROUP BY messages_reply.id LIMIT 3";
i know that what i wrote means that bring me 3 replies only, so how do i bring 3 replies from each user in my users table?
In many databases, you can use row_number() for this:
select *
from (
select mr.*, u.*, row_number() over(partition by u.id order by mr.id desc) rn
from messages_reply mr
inner join users u on mr.from_id = u.id
) t
where rn <= 3
If you are running MySQL < 8.0, as I suspect from the lax use of group by in your query:
select mr.*, u.*
from messages_reply mr
inner join users u on mr.from_id = u.id
where mr.id >= (
select mr1.id
from messages_reply mr1
where mr1.from_id = u.id
order by mr1.id desc
limit 2, 1
)
This gives you the 3 message replies with the greatest id for each user.
Query not tested, just a concept
SELECT *
FROM users
LEFT JOIN (
SELECT *
FROM messages_reply
WHERE from_id = users.id
ORDER BY <your wanted order field> DESC
LIMIT 3) replies
ON users.id = replies.from_id

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.

MySQL select top rows with same condition values

I don't know how to title this problem. Correct me if you have better words.
I have two tables, Users and Posts.
Users:
id | username | password | ...
Posts:
id | author_id | title | content | ...
Now I want to list the "most active" users - the users who have written the most posts. And specifically, I want the top 10 result.
SELECT u.username, COUNT(p.id) AS count
FROM Posts p, Users u
WHERE u.id=p.author_id
GROUP BY p.author_id
ORDER BY count DESC
LIMIT 10;
I can get the expected result. However, the ranking may not be "fair" if some users have same number of posts.
E.g., I may get results like:
User 1 | 14
User 2 | 13
...
User 9 | 4
User 10 | 4
Here, there are actually several more users who have 4 posts.
So, the top 10 could be not exactly 10 results. How can I get a more "fair" result that contains extra rows of users who have 4 posts?
This is the right solution, I think: you need the subquery to know how much post has the 10th place in your top ten. Then, you use the outer query to extract the users with almost that postcount.
SELECT u.username, COUNT(p.id) AS count
FROM Posts p
JOIN Users u ON u.id = p.author_id
GROUP BY p.author_id
HAVING COUNT(p.id) >=
(
SELECT COUNT(p.id) AS count
FROM Posts p
JOIN Users u ON u.id = p.author_id
GROUP BY p.author_id
ORDER BY count DESC
LIMIT 9, 1
)
ORDER BY count DESC
Maybe not the best solution
select u.username, COUNT(p.id) AS count
FROM Posts p
join Users u on u.id = p.author_id
GROUP BY p.author_id
having COUNT(p.id) in
(
SELECT COUNT(p.id)
FROM Posts p
join Users u on u.id = p.author_id
GROUP BY p.author_id
ORDER BY count DESC
LIMIT 10
)
ORDER BY count DESC
Try this:
SELECT username, PostCount
FROM (SELECT username, PostCount, IF(#PostCount = #PostCount:=PostCount, #idx:=#idx+1, #Idx:=1) AS idx
FROM (SELECT u.username, COUNT(p.id) AS PostCount
FROM Posts p
INNER JOIN Users u ON u.id=p.author_id
GROUP BY p.author_id
) AS A, (SELECT #PostCount:=0, #Idx:=1) AS B
ORDER BY PostCount DESC
) AS A
WHERE idx <= 10;

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

problem in mysql query with join and limit the time

i have this
SELECT COUNT(1) cnt, a.auther_id
FROM `posts` a
LEFT JOIN users u ON a.auther_id = u.id
GROUP BY a.auther_id
ORDER BY cnt DESC
LIMIT 20
its work fine
bu now i want select from posts which added from 1 day tried to use
WHERE from_unixtime(post_time) >= SUBDATE(NOW(),1)
but its didnot worked
any one have idea
My guess is that you added the WHERE clause in the wrong place. It should come after the JOIN but before the GROUP BY, like this:
SELECT COUNT(1) cnt, a.auther_id
FROM `posts` a
LEFT JOIN users u ON a.auther_id = u.id
WHERE from_unixtime(post_time) >= SUBDATE(NOW(),1)
GROUP BY a.auther_id
ORDER BY cnt DESC
LIMIT 20