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
Related
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
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
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 ...
I have this diagram
What I wanna do is have this output:
How do you manage to do the query of this one?
I have this code
SELECT users.firstname, users.lastname,
users.screenname, posts.post_id, posts.user_id,
posts.post, posts.upload_name,
posts.post_type, posts.date_posted
FROM website.users users
INNER JOIN website.posts posts ON (users.user_id = posts.user_id)
ORDER BY posts.pid DESC
//PROBLEM with this one is that it only views the post from all users.
//SO I added
SELECT COUNT(user_id) AS friends, SUM(user_id = ?) AS you, user_id
FROM feeds WHERE post_id = ?
//This one will give you two fields containing how many different users **feeds** the
post
Please help guys. Actually this one I am just following Facebook's "LIKE" status
the only thing is I'm not an amateur with this kind of stuff so I'd be glad to hear all your answers. I really need your help
If I've understood you correctly, you want an outer join with the feeds table (in order to retain all posts even if there are no associated feeds), then GROUP BY post.pid in order to amalgamate together all such feeds for each post, and SELECT the desired information.
I use MySQL's GROUP_CONCAT() function to obtain a comma-separated list of all users (up to group_concat_max_len) who have
a "feed" for the given post (you can change the delimiter with the SEPARATOR modifier, if so desired).
SELECT users.firstname, users.lastname,
users.screenname, posts.post_id, posts.user_id,
posts.post, posts.upload_name,
posts.post_type, posts.date_posted,
COUNT(feeds.user_id) AS friends, -- number of "likes"
SUM(feeds.user_id = ?) AS you, -- did I like this?
GROUP_CONCAT(feeds.user_id) -- who likes it?
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)
GROUP BY posts.pid
ORDER BY posts.pid DESC
UPDATE
To obtain the full name of users who have "liked" the post, excluding oneself, one needs to join the users table a second time:
SELECT users.firstname, users.lastname,
users.screenname, posts.post_id, posts.user_id,
posts.post, posts.upload_name,
posts.post_type, posts.date_posted,
COUNT(feeds.user_id) AS friends, -- number of "likes"
SUM(feeds.user_id = ?) AS you, -- did I like this?
GROUP_CONCAT(
CASE WHEN NOT likes.user_id = ? THEN -- exclude self
CONCAT_WS(' ', likes.firstname, likes.lastname) -- full names
END
)
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
If You want to do it for all the users and simultaneously get the feeds, You have to join this feed table:
SELECT u.firstname, u.lastname,
u.screenname, p.post_id, p.user_id,
p.post, p.upload_name,
p.post_type, p.date_posted,
COUNT(f.user_id) AS friends, SUM(f.user_id = ?) AS you
FROM website.users u
INNER JOIN website.posts p ON (u.user_id = p.user_id)
LEFT JOIN website.feeds f ON (p.post_id = f.post_id)
GROUP BY p.pid
ORDER BY p.pid DESC
This one should do the trick...
I have created a feature where users can start new topics (similar to forums).
At the moment on a page, the query for the topics are as follows:
$q = "SELECT ".TBL_COMMUNITYTHREADS.".title, ".TBL_COMMUNITYTHREADS.".id,
".TBL_COMMUNITYTHREADS.".date, ".TBL_COMMUNITYTHREADS.".author, ".TBL_USERS.".username FROM ".TBL_COMMUNITYTHREADS."
INNER JOIN ".TBL_USERS." ON ".TBL_COMMUNITYTHREADS.".author = ".TBL_USERS.".id
WHERE type = '$type'
ORDER BY date DESC LIMIT $offset, $rowsperpage ";
The tables are constants and the offset and rowsperpage are variables passed in to limit how many posts are on a page.
At the moment though, all the topics are ordered by the date.
I want them to be ordered by the latest response.
Similarly to forums, when the reponse inside the topic is newest, that topic will go to the top.
The topics are stored in tbl_communitythreads and the replies in tbl_communityreplies.
How can I ordered them by the latest repsonse.
They are linked by the threadid in tbl_communityreplies. Also in that one is the date column.
Thankyou for reading, I just cant think of how to do this.
This:
SELECT c.title, c.id, c.date, c.author, u.username,
(
SELECT MAX(reply_date)
FROM tbl_communityreplies cr
WHERE cr.thread = c.id
) AS last_reply
FROM TBL_COMMUNITYTHREADS c
JOIN TBL_USERS u
ON u.id = c.author
ORDER BY
last_reply DESC, c.id DESC
LIMIT $offset, $rowsperpage
or this:
SELECT c.title, c.id, c.date, c.author, u.username
FROM (
SELECT cr.thread, cr.reply_date, cr.id
FROM tbl_communityreplies cr
WHERE (cr.last_reply, cr.id) =
(
SELECT last_reply, id
FROM tbl_communityreplies cri
WHERE cri.thread = cr.thread
ORDER BY
thread DESC, last_reply DESC, id DESC
)
ORDER BY
last_reply DESC, id DESC
LIMIT $offset, $rowsperpage
) q
JOIN TBL_COMMUNITYTHREADS c
ON c.id = q.thread
JOIN TBL_USERS u
ON u.id = c.author
ORDER BY
q.reply_date DESC, q.id DESC
The former query is more efficient for large values of $offset, or if you have few threads with lots of replies.
Issue the following commands:
CREATE INDEX ix_communitythreads_replydate_id ON TBL_COMMUNITYTHREADS (reply_date, id)
CREATE INDEX ix_communitythreads_thread_replydate_id ON TBL_COMMUNITYTHREADS (thread, reply_date, id)
for this to work fast.
by join with another table , then you can order by column from this table.