Making a user profile activity feed - mysql

I need to build an activity feed to go on each users profile page showing what they have been doing on the site.
There is three tables: comments, ratings, users
I want the feed to include the comments and ratings that the user has posted.
in the comments and ratings table it stores the user id of the user who posted it, not the username, so in for each item in the news feed it needs to select from the users table where the user id is the same to retrieve the username.
All the entries in the feed should be ordered by date.
Here is what ive got even though i know it is not correct because it is trying to match both with the same row in the users table.
SELECT comments.date, comments.url AS comment_url, comments.user_id, ratings.date, ratings.url AS rating_url, ratings.user_id, users.id, users.username
FROM comments, ratings, users
WHERE comments.user_id=%s
AND comments.user_id=users.id
AND ratings.user_id=%s
AND ratings.user_id=users.id
ORDER BY ratings.date, comments.date DESC

JOIN. It seems you know that, but here's how:
SELECT * FROM comments LEFT JOIN users ON comments.user_id = users.id
Thus, as far as I can tell, you're trying to order two separate things at the same time. The closest I think I can come up with would be something like:
(SELECT comments.date AS date, users.username AS name, comments.url AS url CONCAT('Something happened: ',comments.url) AS text
FROM comments LEFT JOIN users ON comments.user_id = users.id
WHERE users.id = %s)
UNION
(SELECT ratings.date AS date, users.username AS name, ratings.url AS url CONCAT('Something happened: ',ratings.url) AS text
FROM comments LEFT JOIN users ON comments.user_id = users.id
WHERE users.id = %s)
ORDER BY date DESC LIMIT 0,10
Note that the columns of both parts of the union match up. I'm pretty sure that that is required for something like this to work. That's why I have that CONCAT statement, which lets you build a string that works differently between ratings and comments.

Related

mysql tables: Join to two tables in a request

Newbie here.. Here's what I'm trying to do.
I have a Posts table with the following columns
id, userid, bodyText, date
and I have another table for users users.
When users submit a post, the user-id saves into the "posts" table under "userid". Well, I want to display that users information, such as name and picture, on the posts using the "userid" to get each users information so that their name and picture shows along with the post they submitted.
Sorry if I'm not being clear, english is not my first language and like I said, I'm new at this and still trying to learn.
I had it where when they submit the post, their name and picture also saves into the "posts" table but I want to change it because if the user updates their name or picture, it will still show the name and picture they had when they submitted the post. I want their name and picture to update on the posts if they update their information on the users table.
What you are asking about is a JOIN. In general the Join will look like
SELECT p.id. p.bodyText, p.date, u.name, u.picture FROM posts as p INNER JOIN users as u ON p.user_id = u.id where p.id = 123;
This will select the post with the ID 123 from the posts table and joins the users information from the users table based on the user_id columns value from the posts table.
In Syntax this could be something like
$sth = $dbh->prepare("SELECT p.id. p.bodyText, p.date, u.name, u.picture FROM posts as p INNER JOIN users as u ON p.user_id = u.id where p.id = ?");
$sth->execute(array(123));
$red = $sth->fetchAll();

Join results from two tables when data can appear in multiple columns in one table

I have one table containing a list of users, all I need from this are users.id and users.username
I have a second table that links the users as "friends", all I need from this is friends.one and friends.two
I want to output a result that shows all friends of a user with a certain user id (this will be a variable, but for the sake of the example we'll use user id '1'). User id '1' can appear in either friends.one or friends.two.
I've tried a few different ideas, but I'm not sure I'm any closer. The code below is obviously awful but I think it describes the idea well(ish). Though I'm probably overly complicating something which there is an easier method for,
SELECT users.username, users.id
FROM users
INNER JOIN friends
ON users.id = friends.friendone
WHERE friends.friendtwo='1'
UNION
SELECT users.username, users.id
FROM users
INNER JOIN friends
ON users.id = friends.friendtwo
WHERE friends.friendone='1'
ORDER BY users.username ASC;
With conditional join:
SELECT u.username, u.id
FROM friends f INNER JOIN users u
ON u.id = CASE '1'
WHEN f.friendone THEN f.friendtwo
WHEN f.friendtwo THEN f.friendone
END

SQL Query JOIN with 4 tables

Who can help me?
I have 4 tables posts, users, users details and comments.
Here is the strucutre:
posts
id
title
description
users
id
username
password
users_details
id
user_id
avatar
location
comments
id
post_id
user_id
parent
comment
posted
I have a query which i want to display comments on specific post.
This is what i written but avatar column it doesn't show any results. It seems i written it wrong on join or something.
SELECT comments.id as comment_id,
comments.user_id as user_id,
comments.post_id as post_id,
comments.parent as parent,
comments.comment as comment,
comments.posted as posted,
users_details.avatar as avatar,
users.username as username
FROM `comments`
LEFT JOIN users ON users.id = comments.user_id
LEFT JOIN users_details ON users_details.user_id = users.id
WHERE comments.post_id='60337'
ORDER BY posted ASC
Here is a screenshot of the table with results https://i.imgur.com/VQ8KwV1.png
I want to mention the avatar field it has a value for that user in users_details table so it should be displayed...
Thanks!
Two potential reasons I could tell causing this issue.
1. The users do not have an avatar.
Try: Select Avatar from Users_Details where User_Id in (2,9212) and make sure it returns some data.
2. The Primary/Foreign key being used for joining the tables is not matching
Run those queries below and ensure that they are returning the same users.
select * from users where id in (2,9212)
select * from users_details where user_id in (2,2912)

use COUNT(*) values from one table to another

Suppose I have two tables, users and posts. Posts has the following fields, userid, postid, etc and userid can appear multiple times as one user can write multiple posts....I'm just trying sort the users table based off the # of occurrences per userid in the posts table. I can get the # of occurrences per user using this
SELECT userid, COUNT(*)
FROM posts
GROUP BY userid;
I would like to use the values under COUNT(*) column, maybe add it to my other table because then I can simply to something like this
SELECT * FROM users
ORDER BY newcolumn ASC;
but I'm having trouble doing that. Or can I do it without having to add an extra column? Hints please. Thanks
Left join is the key here!
SELECT users.userid,count(posts.userid) AS total_count
FROM users
LEFT JOIN posts on posts.userid = users.userid
GROUP BY users.userid
ORDER BY total_count DESC;
We are taking the left join on two tables with same user_id and we are counting the total number of posts per user using group by. Finally sort by count and show results.
try an left join:
select users.userid, [user fields],count(postid) as posts_count
from users
left join posts on posts.userid = users.userid
group by users.userid,[user fields]
order by posts_count desc.
You want to select users (FROM users) but you want to sort based on criteria in another table (COUNT(*) FROM posts) -- therefore you need to use a JOIN
Off-hand I can't seem to recall if "JOIN" or "RIGHT JOIN" or "FULL JOIN" is what you need if you wanted to get a cartesian product of the tables then group and aggregate on a single field, but I can avoid the need to remember with a subquery (hopefully someone will soon post a smaller and smarter answer):
SELECT users.* FROM users
JOIN (
SELECT userid, COUNT(*) as count
FROM posts
GROUP BY userid
) as subquery ON users.id = subquery.userid
ORDER BY subquery.count
Note: I haven't tested this query, but it looks good to me. Again: hopefully someone will post a better answer soon as I'm not doing my due dilligence, but you definitely need a JOIN :)
You could add a post_count column to the users table, but you would also have to update that count column every time a user creates a new post and you would have to build that logic into your application.
Otherwise, it looks like the answer from FallAndLearn will get you what you need.

How to format this MySQL query?

I have a table posts with columns board_id, author_id, message. I have another table users with columns id, name, avatar_url.
I need to write a query to get all of the users that have posted on a given board, with no duplicates. The query should return the full user row (id, name, avatar_url).
I've tried
SELECT DISTINCT users.*, posts.author_id
FROM users
INNER JOIN posts
ON users.id = posts.author_id
WHERE posts.board_id = [desired board ID]
but that's giving me duplicates of each user.
There is also the possibility that my query is correct and I've goofed on something elsewhere...
Here's a simple query that will get you all the rows in users with post activity w/o duplication
SELECT * FROM USERS
WHERE id IN (SELECT author_id FROM posts WHERE board_id = [desired board]
You could also use your basic syntax with a distinct on everything you need distinct, e.g.:
SELECT DISTINCT users.*
FROM users
JOIN posts ON users.id = posts.author_id
WHERE posts.board_id = [desired board ID]
Just group by the user id, like so:
SELECT users.id, MIN(users.name), MIN(users.avatar_url)
FROM users
INNER JOIN posts
ON users.id = posts.author_id
WHERE posts.board_id = [desired board ID]
GROUP BY users.id
SELECT users.id, users.name, users.avatar_url, posts.author_id
FROM users
INNER JOIN posts
ON users.id = posts.author_id
WHERE posts.board_id = [desired board ID] GROUP BY users.id
This will get all found rows and then group them by the userid so each user id will appear just once, hence each user row [who posts on the board] will appear just once.
Yet better is use with annotation not for highlighted after IN, which defense against duplicate values. That's it.