SQL multiple joins SELECT query - php

I've build the following query
$subforumsquery = "
SELECT
forums.*,
posts.title AS lastmsgtitle,
posts.timee AS lastmsgtime,
posts.useraid AS lastmsguseraid,
posts.useradn AS lastmsguseradn,
users.photo AS lastmsgphoto
FROM forums
LEFT JOIN posts
ON (posts.forumid = forums.id)
LEFT JOIN users
ON (posts.useraid = users.id)
WHERE forums.relatedto = '$forumid'
and posts.type = 'post'
ORDER BY `id` DESC";
I don't know why, but i get the same subforum twice even that there is only 1 sub forum.
BTW, is there any way to select only the last post insted of searching all?
Thanks!

Use group by
SELECT
forums.*,
posts.title AS lastmsgtitle,
posts.timee AS lastmsgtime,
posts.useraid AS lastmsguseraid,
posts.useradn AS lastmsguseradn,
users.photo AS lastmsgphoto
FROM forums
LEFT JOIN posts
ON (posts.forumid = forums.id)
LEFT JOIN users
ON (posts.useraid = users.id)
WHERE forums.relatedto = '$forumid'
and posts.type = 'post'
GROUP BY forums.id
ORDER BY `id` DESC
EDIT :
Use MAX with a derieved query
SELECT
forums.*,
posts.title AS lastmsgtitle,
posts.timee AS lastmsgtime,
posts.useraid AS lastmsguseraid,
posts.useradn AS lastmsguseradn,
users.photo AS lastmsgphoto
FROM forums
LEFT JOIN (
SELECT
*
FROM posts
LEFT JOIN (
SELECT
MAX(id) AS ID
FROM posts
GROUP BY forumid
) AS l ON l.ID = posts.id
GROUP BY forumid) AS posts
ON posts.forumid = forums.id
LEFT JOIN users
ON (posts.useraid = users.id)
WHERE forums.relatedto = '$forumid'
and posts.type = 'post'
GROUP BY forums.id
ORDER BY `id` DESC

Related

Adding a JOIN to query resulting in a fail

I am trying to add my users table to my existing query so that I can match the users.id with the forum_topics.topic_creator, so I can match those and enable myself to assign that with that users username.
This is my original query.
$query2 = mysqli_query($con,"SELECT t.*, COUNT(p.topic_id)
AS tid2 FROM forum_topics AS t JOIN forum_posts
AS p on t.id = p.topic_id WHERE t.category_id = ".$cid."
GROUP BY t.id DESC")
I then tried doing this..
$query2 =mysqli_query($con,"SELECT t.*, COUNT(p.topic_id)
AS tid2 FROM forum_topics AS t JOIN forum_posts
AS p on t.id = p.topic_id WHERE t.category_id = ".$cid."
INNER JOIN users AS u
ON t.topic_creator = u.id
GROUP BY t.id DESC")
or die ("Query2 failed: %s\n".($query2->error));
I am getting the fail message.
What am I doing wrong?
WHERE clause should come after join:
SELECT t.*, COUNT(p.topic_id) AS tid2
FROM forum_topics AS t JOIN
forum_posts AS p on t.id = p.topic_id INNER JOIN
users AS u ON t.topic_creator = u.id
WHERE t.category_id = ".$cid."
GROUP BY t.id DESC
EDIT:
To select the username as well:
SELECT t.*,u.username, COUNT(p.topic_id) AS tid2
FROM forum_topics AS t JOIN
forum_posts AS p on t.id = p.topic_id INNER JOIN
users AS u ON t.topic_creator = u.id
WHERE t.category_id = ".$cid."
GROUP BY t.id DESC
The WHERE clause has to be placed after the INNER JOIN.
$query2 =mysqli_query($con,"SELECT t.*, COUNT(p.topic_id)
AS tid2 FROM forum_topics AS t
JOIN forum_posts AS p ON t.id = p.topic_id
INNER JOIN users AS u ON t.topic_creator = u.id
WHERE t.category_id = ".$cid."
GROUP BY t.id DESC")
or die ("Query2 failed: %s\n".($query2->error));
Try this
SELECT t.*, COUNT(p.topic_id) AS tid2
FROM forum_topics t
JOIN forum_posts p ON (t.id = p.topic_id )
INNER JOIN users u ON (t.topic_creator = u.id)
WHERE t.category_id = ".$cid."
GROUP BY t.id DESC`

SQL join QUERY multiple tables and SELECT's

I build the following query,
SELECT
posts.id,
posts.useraid,
posts.useradn,
posts.title,
posts.createdate,
posts.forumid,
posts.type,
posts.totalreplys,
users.photo AS creatorphoto
FROM posts
JOIN users ON(users.id = posts.useraid)
WHERE posts.forumid IN(
SELECT subscribe.forumid AS fsub
FROM subscribe
WHERE subscribe.useraid = '$myid'
) AND
posts.forumid IN(
SELECT forums.id
FROM forums
WHERE forums.relatedto=fsub
)
AND posts.type='post'
ORDER BY posts.timee DESC LIMIT 20
The code works perfectly without this part
AND
posts.forumid IN(
SELECT forums.id
FROM forums
WHERE forums.relatedto=fsub
)
But, I need the query to select all posts from all forums he subscribe to, including the subforums posts.
'fsub' has no scope here, it doesn't really even exist at this point in your query:
posts.forumid IN(
SELECT forums.id
FROM forums
WHERE forums.relatedto=fsub
)
You need to use a UNION I believe.
Instead of using sub-queries why don't you just add the subscribe and forums table to the main FROM criteria?
e.g.,
FROM posts
JOIN users ON(users.id = posts.useraid)
JOIN subscribe ON (posts.forumid = subscribe.forumid)
JOIN forums ON (forums.relatedto = posts.forumid)
Try this:
SELECT
posts.id,
posts.useraid,
posts.useradn,
posts.title,
posts.createdate,
posts.forumid,
posts.`type`,
posts.totalreplys,
users.photo AS creatorphoto
FROM posts
JOIN users
ON users.id = posts.useraid AND posts.`type`='post'
JOIN subscribe
ON subscribe.forumid = posts.forumid AND subscribe.useraid = '$myid'
JOIN forums
ON posts.forumid = forums.relatedto
ORDER BY posts.timee DESC LIMIT 20
This is your answer, you need first join the subscribe and forms before search it with subquery.
SELECT
posts.id,
posts.useraid,
posts.useradn,
posts.title,
posts.createdate,
posts.forumid,
posts.type,
posts.totalreplys,
users.photo AS creatorphoto
FROM posts
JOIN users ON(users.id = posts.useraid)
WHERE posts.forumid IN(
SELECT subscribe.forumid AS fsub
FROM subscribe ,forums
WHERE subscribe.useraid = '$myid'
and forums.relatedto = subscribe.forumid
and forums.id = subscribe.forumid
)
AND posts.type='post'
ORDER BY posts.timee DESC LIMIT 20

SQL multiple joins SELECT query with MAX()

The following query select the subforums from the database and the last posts in each one of them.
SELECT
forums.*,
MAX(posts.id),
posts.title AS lastmsgtitle,
posts.timee AS lastmsgtime,
posts.useraid AS lastmsguseraid,
posts.useradn AS lastmsguseradn,
users.photo AS lastmsgphoto
FROM forums
LEFT JOIN posts
ON(posts.forumid = forums.id)
LEFT JOIN users
ON(posts.useraid = users.id)
WHERE forums.relatedto='$forumid'
and posts.type='post'
GROUP BY forums.id
ORDER BY `id` DESC
The only problem, the query not select the last post, any ideas why?
FORUMS 1
POSTS 2
I would suggest using a subquery to select the max(id) for each post.
SELECT
f.*, -- replace the f.* with the columns that you need to return
p1.MaxId,
p2.title AS lastmsgtitle,
p2.timee AS lastmsgtime,
p2.useraid AS lastmsguseraid,
p2.useradn AS lastmsguseradn,
u.photo AS lastmsgphoto
FROM forums f
LEFT JOIN
(
select MAX(id) MaxId, forumid
from posts
group by forumid
) p1
ON p1.forumid = f.id
LEFT JOIN posts p2
ON p2.forumid = f.id
and p1.MaxId = p2.id
and p2.type='post'
LEFT JOIN users u
ON p2.useraid = u.id
WHERE f.relatedto='$forumid'
ORDER BY `id` DESC

mysql related fields

These 4 fields are related to each other
I want it to output it as:
In my query:
SELECT users.firstname, users.lastname, users.screenname, posts.post_id, posts.user_id,
posts.post, posts.upload_name, posts.post_type,
DATE_FORMAT(posts.date_posted, '%M %d, %Y %r') AS date,
COUNT(NULLIF(feeds.user_id, ?)) AS everybody, SUM(feeds.user_id = ?) AS you,
GROUP_CONCAT(CASE WHEN NOT likes.user_id = ? THEN
CONCAT_WS(' ', likes.firstname, likes.lastname)
END
) as names
FROM website.users users
INNER JOIN website.posts posts ON (users.user_id = posts.user_id)
LEFT JOIN website.feeds feeds ON (posts.post_id = feeds.post_id)
LEFT JOIN website.users likes ON (feeds.user_id = likes.user_id)
GROUP BY posts.pid
ORDER BY posts.pid DESC
Now, I am having a problem on which part should I join the friends table,
I want to display all the posts from friend_id or user_id and also the post from user who is currently logged in. If no friend matched on the friend table, then just output all the posts from user. Please guys I need your help.
friends.friend_id = friend of the current user
friends.user_id = current friend of the user
Thus, friends.friend_id = posts.user_id or friends.user_id = posts.user_id
If my friends table is not understandable, please help me change it to make it better.
You would like to see posts either from the user, or from his friends. Therefore, instead of joining with users, join with the subquery, like this:
SELECT users.firstname, users.lastname, users.screenname,
posts.post_id, posts.user_id, posts.post, posts.upload_name,
posts.post_type, DATE_FORMAT(posts.date_posted, '%M %d, %Y %r') AS date,
COUNT(NULLIF(feeds.user_id, ?)) AS everybody,
SUM(feeds.user_id = ?) AS you,
GROUP_CONCAT(CASE WHEN NOT likes.user_id = ? THEN
CONCAT_WS(' ', likes.firstname, likes.lastname) END) as names
FROM (SELECT user_id FROM website.users WHERE user_id = ?
UNION ALL
SELECT user_id FROM website.friends WHERE friend_id = ?
UNION ALL
SELECT friend_id FROM website.friends WHERE user_id = ?) AS who
JOIN website.users users ON users.user_id = who.user_id
JOIN website.posts posts ON users.user_id = posts.user_id
LEFT JOIN website.feeds feeds ON posts.post_id = feeds.post_id
LEFT JOIN website.users likes ON feeds.user_id = likes.user_i)
GROUP BY posts.pid
ORDER BY posts.pid DESC;
Test output here.
If i well understood you want to JOIN the friends table based on the friends = user_id and if not match JOIN on user_id of the friends table, so you can try with something like this :
SELECT users.firstname, users.lastname, users.screenname, posts.post_id, posts.user_id,
posts.post, posts.upload_name, posts.post_type,
DATE_FORMAT(posts.date_posted, '%M %d, %Y %r') AS date,
COUNT(NULLIF(feeds.user_id, ?)) AS friends, SUM(feeds.user_id = ?) AS you,
GROUP_CONCAT(CASE WHEN NOT likes.user_id = ? THEN
CONCAT_WS(' ', likes.firstname, likes.lastname)
END
) as names
FROM website.users users
INNER JOIN website.posts posts ON (users.user_id = posts.user_id)
LEFT JOIN website.feeds feeds ON (posts.post_id = feeds.post_id)
LEFT JOIN website.users likes ON (feeds.user_id = likes.user_id)
LEFT JOIN website.friends friends ON ((posts.user_id = friends.user_id) OR (posts.user_id = friends.friends_id) )
GROUP BY posts.pid
ORDER BY posts.pid DESC
I have basically added a JOIN with friends table with an OR on the two fields that you seem want to JOIN ...

Why does adding count() to my sql query stop it from working?

Why does this return 23 rows (the right amount):
select users.user_id, users.fname, users.lname,
stars.stars, comments.comment from users
LEFT JOIN stars on users.user_id = stars.userid
JOIN comments on users.user_id = comments.sender
where users.user_id = ? order by comments.time desc;
and this return 1 row?:
select users.user_id, users.fname, users.lname,
stars.stars, count(distinct comments.id) as amount,
comments.comment from users
LEFT JOIN stars on users.user_id = stars.userid
JOIN comments on users.user_id = comments.sender
where users.user_id = ? order by comments.time desc;
Cheers.
you need to group the main data or do a sub-query for the field.

Categories