Top users(comments) - php

I have a users table and a comments table and I want to select from users the top users that have the biggest amount of comments from the comments table and order them by numbers of comments
Just the forum comments should be counted(type can be forum,picture,news etc)
table structure
users
id | username | password
comments
id | text | type | author_id

SELECT
u.id,u.username,u.password ,count(c.id) as total
FROM
users u
JOIN comments c on c.author_id = u.id
GROUP BY u.id
ORDER BY total DESC;
This should do the trick, try and let us know how it worked out for you
UPDATE
For details on how to do this you will fall inlove with this article
Update : New Link, old one is broken Databases

Tested on PostgreSQL 8.1:
select users.id, count(comments.author_id)
from users, comments
where users.id = comments.author_id
group by users.id
order by 2 desc

SELECT users.id, users.name, COUNT(comments.id) AS cnt
FROM users
LEFT JOIN comments ON users.id = comments.author_id
WHERE type IN ('forum', 'picture', 'news', 'etc')
GROUP BY users.id
ORDER BY cnt DESC
LIMIT 10
Get the 10 most prolific commenter where the comment type is 'form', 'picture', 'news', or 'etc'.

Related

Finding username of the last post in mysql table joining 3 tables

I know I am doing this qry wrong - its taking over 10secs for the results to come back w/ only 3000 rows of data...
I have 3 tables:
users
id
username
DATA:
1|tom
2|dick
3|harry
posts
id
id_users
DATA:
1|1
2|1
3|1
4|2
5|2
6|3
cronjobs
id
id_post
id_wall
DATA: id|id_post|id_wall
1|1|1
2|1|2
3|1|3
4|1|4
5|1|5
6|2|5
7|4|3
8|6|3
9|4|4
A user will make a post
That post will be put on one or more walls and stored in the cronjobs table.
The id on cronjobs is auto increment.
I need to get the username and last post on each wall.
In the above example
Dick was the last person to post on wall 4 with post 4
Harry was the last person to post on wall 3 with post 6
Tom was the last person to post on wall 5 with post 2
Tom was the last person to post on wall 2 with post 1
Tom was the last person to post on wall 1 with post 1
Here is the qry im currently using, I know using the IN clause with the select inside it, is killing this....
SELECT
c.id,
c.id_post,
c.id_wall AS id_wall,
p.id_users AS user_id,
u.NAME AS username
FROM
cronjobs c,
posts p,
users u
WHERE c.id IN
(SELECT MAX(id)
FROM
cronjobs
GROUP BY id_wall)
AND c.id_post = p.id
AND p.id_users = u.id
ORDER BY c.id
Any help is appreciated!
Try this
SELECT
c.id,
c.id_post,
c.id_wall AS id_wall,
p.id_users AS user_id,
u.NAME AS username
FROM
cronjobs c,
posts p,
users u ,
(SELECT MAX(id) as id
FROM
cronjobs
GROUP BY id_wall) table_id
where c.id_post = p.id
AND p.id_users = u.id
and table_id.id =c.id
ORDER BY c.id
You can use join instead of a subquery in where clause, subquery in join part will be executed once while subquery in where clause will be executed for all the resultant rows this query will perform much better than yours, also index your columns that appears in on() part
SELECT
c.id,
c.id_post,
c.id_wall AS id_wall,
p.id_users AS user_id,
u.username AS username
FROM
cronjobs c
join (SELECT MAX(id) id ,id_wall
FROM cronjobs
GROUP BY id_wall) c1 on c.id = c1.id and c.id_wall = c1.id_wall
join posts p on c.id_post = p.id
join users u on p.id_users = u.id
ORDER BY c.id
DEMO

Select each first record with id in another table's result

I have two tables, Users(id, username) and Posts(id, user_id, content). I want to list a summary of them which, I want to list all users and the first post of each user. How can I realize this in one query?
I tried something like.
QUERY
SELECT Users.*, Posts.content
FROM Users, Posts
WHERE Posts.user_id=T_Users.id
But it will return all posts for each user (I cannot add LIMIT 1 at the tail of course which only returns one user).
Some sample records:
Users table:
id username
1 test1
2 test2
Posts table:
id user_id content
1 1 This is a test1's content.
2 1 This is another test1's content.
3 2 This is a test2's content.
And I want the result:
Users.id Users.username Posts.content
1 test1 This is a test1's content.
2 test2 This is a test2's content.
Here is one approach to get the latest record per user i assume the latest record will be considered as the minimum post id
SELECT u.*, p.content
FROM Users u
join Posts p on p.user_id=u.id
join (select user_id ,min(id) id from Posts group by user_id ) p1
on (p.id = p1.id and p.user_id = p1.user_id )
Demo
Try this
select min(x.id) as Id,x.user_id,x.content from(
select p.id,p.user_id,p.content from Users u inner join Posts p
on u.id=p.user_id and u.gender=1
)x group by x.user_id
Have you tried group by clause.
SELECT Users.*, Posts.content
FROM Users, Posts
WHERE Posts.user_id=T_Users.id GROUP BY Posts.user_id

Inner Join Query Advice

i need help on creating an inner join query.
I have 2 tables, blogs and followers.
In the blogs table i have all the blog information, and then in the followers i have two fields which are the user id and then the blog id that the user follows.
I want to create a query that will order the blogs by how many followers there are.
So this is an example of what i use to show what builds a user is following (for reference):
$query = "SELECT * FROM blogs INNER JOIN followers ON (blogs.id = followers.blogid) WHERE followers.userid='" .$usernamesesh. "'";
How can i go about creating a similiar query that will select all the blogs, but order them by highest to lowest followers.
Hope this makes sense, i cant get my head around this one for some reason!
The only other option is to add a number of followers field in the blogs table but that would involve changing my follow script etc.
Craig.
Without knowing the exact structure of you tables it's hard to tell. Assuming your followers table looks something like this
blogid | userid
-------+----------
1 | 2
-------+----------
1 | 1
-------+----------
1 | 3
-------+----------
2 | 2
-------+---------
SELECT blogid, COUNT(userid) AS UserCount FROM followers
GROUP BY blogid ORDER BY UserCount DESC;
You can then to join the blogs table to get what ever columns you need from that table.
SELECT blogs.*, IFNULL(f.UserCount,0) AS UserCount
FROM blogs
LEFT JOIN (
SELECT blogid, COUNT(userid) AS UserCount FROM followers
GROUP BY blogid
) f
ON f.blogid = blogs.id
ORDER BY UserCount DESC
I would recommend tweaking Mihai's suggestion a little bit, so add this string to the end of your query: GROUP BY blogs.id ORDER BY COUNT(userid) DESC
$query = "SELECT blogs.id, count(*) AS total FROM blogs INNER JOIN followers ON (blogs.id = followers.blogid) WHERE followers.userid='" .$usernamesesh. "'" GROUP BY blogs.id ORDER BY total;
Hope this helps
You could join against a subquery:
SELECT blogs.*, s.cnt
FROM blogs
LEFT JOIN (SELECT blogid, count(*) as cnt
FROM followers
GROUP BY blogid) s
ON s.blogid = blogs.id
ORDER BY s.cnt
Edit
With
CREATE TABLE blogs (id);
create TABLE followers(blogid);
INSERT into blogs values (1),(2),(3);
INSERT into followers values (1),(1),(3);
You get:
id cnt
---------- ----------
2
3 1
1 2

Selected by groups with totals (mySQL)

I've been fiddleing with this about 20 minutes now and though I might get some help here. I have two tables, in a many-to-one relationship. users (one) and events (many). The tables, simplified, look like this:
users
-----------
user_id
group_id
events
-----------
user_id
I'm trying to produce a report that will show the number of users with at least one event, per group. so a result set would hopefully look like:
group_id users_with_at_least_one_event
1 689
2 312
SELECT group_id, count(*) users_with_at_least_one_event
FROM
(
SELECT u.user_id, u.group_id, count(*) as event_count
FROM users u
JOIN events e
ON u.user_id = e.user_id
GROUP BY u.user_id, u.group_id
HAVING count(*) > 1
) sub
GROUP BY group_id
SELECT group_id, COUNT(users.user_id) AS users_with_at_least_one_event,
FROM users, events
WHERE users.user_id = events.user_id
GROUP BY group_id
maybe?
try
select users.group_id, count(distinct users.user_id) as users_with_at_least_one_event
from
users, events
where users.user_id = events.user_id
group by users.group_id
SELECT users.group_id, COUNT(*) FROM users
WHERE users.user_id IN (SELECT events.user_id FROM events)

Mysql subquery fails, need help :)

I have a table PICTURES:
username varchar(50)
picture_id varchar(50)
datetime
...and I have a table FRIENDS:
user_1 varchar(50)
user_2 varchar(50)
datetime
When you have friends on the website your username goes in user_1, and your friend username's go in user_2. For each new friend a new row...
I want to show the 5 last pictures of the friends of one user (user_1)
so I try
SELECT p.picture_id, p.datetime
FROM pictures AS p
WHERE p.username = (
SELECT f.user_2
FROM friends AS f
WHERE f.user_1 = '(ENTER USERNAME HERE)'
ORDER BY f.datetime DESC
LIMIT 5
)
ORDER BY p.datetime DESC;
And as you can see, the subquery return more than one row so... I need your help or suggestions to help me managing this solution!
Try using IN instead of = in WHERE p.username = (. Since you're selecting up to 5 rows = doesn't quite make sense.
SELECT p.picture_id, p.datetime
FROM pictures AS p
WHERE p.username IN (
SELECT f.user_2
FROM friends AS f
WHERE f.user_1 = '(ENTER USERNAME HERE)'
ORDER BY f.datetime DESC
LIMIT 5
)
ORDER BY p.datetime DESC;
I suggest you try a JOIN instead:
SELECT
p.picture_id, p.datetime
FROM
friends AS f
INNER JOIN pictures AS p ON f.user_2 = p.username
WHERE
f.user_1 = '(ENTER USERNAME HERE)'
ORDER BY
p.datetime DESC
LIMIT 5
This will give you the last 5 pictures from any of user_1's friends
I assume you mean you want the latest 5 pictures from each of the friends, not the latest 5 pictures among all the friends' pictures.
This is one of the greatest-n-per-group problems that appears so frequently on StackOverflow. Normally the problem is to find the top one from each group, but here's how I solve it when you want the top 5 or some other quantity:
SELECT p1.*
FROM friends AS f
JOIN pictures AS p1 ON (f.user_2 = p1.username)
LEFT OUTER JOIN pictures AS p2 ON (p1.username = p2.username
AND p1.datetime < p2.datetime)
WHERE f.user_1 = ?
GROUP BY p1.picture_id
HAVING COUNT(*) < 5;
Explanation: for each picture p1 that belongs to one of my friends, count the pictures belonging to the same friend and with a more recent datetime. The pictures that are in the most 5 recent must have fewer than 5 other pictures that are more recent.
Try changing the WHERE p.username =(subquery) to WHERE p.username in(subquery)
SELECT p.picture_id, p.datetime FROM pictures AS p WHERE p.username IN (SELECT f.user_2 FROM friends AS f WHERE f.user_1 = '(ENTER USERNAME HERE)' ORDER BY f.datetime DESC LIMIT 5) ORDER BY p.datetime DESC;

Categories