Inner Join Query Advice - php

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

Related

top first friends then the other users from like list

I have tables:
likes - id, user_id, like_user_id<br>
users - id, name, email ...,<br>
friends - id, user_id, friend_id, status<br>
Is it possible to sort it with one SQL query first to show the friends then the other users.
Any help would be appreciated.
Thank you.
I tried this and it works, but the problem is it give me double results of users:
select *
from `likes`
left join `users` on `users.id` = `likes.user_id`
left join `friends` on `friends.user_id` = `likes.user_id`
or `friends.friend_id` = `likes.user_id`
where `likes.id` = 1
order by `friends.user_id` = 5
or `friends.friend_id` = 5
You need to work with a UNION here to merge the liked users with the befriended users. Upon doing this, you can create an artificial column friend, that you fill with 1 in the friend query and 0 in the like query. Later on you can order by that column.
SELECT
friends.user_id,
1 as friend,
users.*
FROM
friends
JOIN users ON users.id = friends.friend_user_id
UNION SELECT
likes.user_id,
0 as friend,
users_liked.*
FROM
likes
JOIN users as users_liked ON likes.like_user_id = users_liked.id
WHERE
user_id = '$userId'
ORDER BY friend DESC, id ASC
This will return a list of all friends, followed by a list of all liked users.

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

mysql multiple COUNT() from multiple tables with LEFT JOIN

I want to show the conclusion of all users.
I have 3 tables.
table post
post_id(index) user_id
1 1
2 3
3 3
4 4
table photo
photo_id(index) user_id
1 2
2 4
3 1
4 1
table video
photo_id(index) user_id
1 4
2 4
3 3
4 3
and in table user
user_id(index) user_name
1 mark
2 tommy
3 john
4 james
in fact, it has more than 4 rows for every tables.
I want the result like this.
id name post photo videos
1 mark 1 2 0
2 tommy 0 1 0
3 john 2 0 2
4 james 1 1 2
5 .. .. .. ..
Code below is SQL that can work correctly but very slow, I will be true appreciated if you help me how it using LEFT JOIN for it. Thanks.
SQL
"select user.*,
(select count(*) from post where post.userid = user.userid) postCount,
(select count(*) from photo where photo.userid = user.userid) photoCount,
(select count(*) from video where video .userid = user.userid) videoCount
from user order by user.id"
(or ORDER BY postCount, photoCount or videoCount ASC or DESC as i want )
I done researched before but no any helped me.
SELECT u.user_id,
u.user_name,
COUNT(DISTINCT p.post_id) AS `postCount`,
COUNT(DISTINCT ph.photo_id) AS `photoCount`,
COUNT(DISTINCT v.video_id) AS `videoCount`
FROM user u
LEFT JOIN post p
ON p.user_id = u.user_id
LEFT JOIN photo ph
ON ph.user_id = u.user_id
LEFT JOIN video v
ON v.user_id = u.user_id
GROUP BY u.user_id
ORDER BY postCount;
Live DEMO
Your method of doing this is quite reasonable. Here is your query:
select user.*,
(select count(*) from post where post.userid = user.userid) as postCount,
(select count(*) from photo where photo.userid = user.userid) as photoCount,
(select count(*) from video where video.userid = user.userid) as videoCount
from user
order by user.id;
For this query, you want the following indexes:
post(userid)
photo(userid)
video(userid)
user(id)
You probably already have the last one, because user.id is probably the primary key of the table.
Note that a left join approach is a bad idea in this case. The three tables -- posts, photos, and videos -- are independent of each other. If a user has five of each, then joining them together would produce 125 intermediate rows. If a user has fifty of each, it would be 125,000 -- a lot of extra processing.
Your answer is probably slow as it is using a correlated sub-query i.e. the sub query is running once for each user_id (unless the optimizer is doing something smart - which shouldn't be counted on).
You could use a left outer join and count or use something temporary like:
SELECT u.user_id,
u.user_name,
ph.user_count AS 'photoCount',
p.user_count AS 'postCount',
v.user_count AS 'videoCount'
FROM user u
INNER JOIN ( SELECT user_id,
COUNT(*) AS user_count
FROM photo
GROUP BY user_id
) ph
ON ph.user_id=u.user_id
INNER JOIN ( SELECT user_id,
COUNT(*) AS user_count
FROM post
GROUP BY user_id
) p
ON p.user_id=u.user_id
INNER JOIN ( SELECT user_id,
COUNT(*) AS user_count
FROM video
GROUP BY user_id
) v
ON v.user_id=u.user_id
There are pros and cons for both (depending on indexes). Always have a look at the query plan (using EXPLAIN for MySQL).

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)

Top users(comments)

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'.

Categories