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.
Related
There are three tables, I would like to get the count of a user's total tweets and the count of likes his total tweets received.
I tried to combine two queries to get what I want but failed. Have looked through several previous questions but still can't figure it out.
Users table
id
name
1
User1
Tweets table
id
UserId (foreign key)
content
1
User1
hello
Likes table
id
UserId (foreign key)
TweetId (foreign key)
1
User1
hello
First query:
SELECT Users.name, Users.id, COUNT(Tweets.UserId) AS UserTweetCount FROM Users
LEFT JOIN Tweets
ON Users.id = Tweets.UserId
GROUP BY Users.id
ORDER BY UserTweetCount DESC;
Second query:
SELECT Users.name, Users.id, COUNT(Likes.UserId) AS UserTweetBeLikedCount FROM Users
LEFT JOIN Likes
ON Users.id = Likes.UserId
GROUP BY Users.id;
I tried like below but would get wrong UserTweetBeLikedCount counts. The counts would be UserTweetCount's, not UserTweetBeLikedCount's. When I ran two queries separately, it worked well. But when I combined them together, it didn't work right.
Don't know how to display the right counts. Can someone give me hints to solve this, please?
SELECT Users.name, Users.id,
COUNT(Tweets.UserId) AS UserTweetCount, COUNT(Likes.UserId) AS UserTweetBeLikedCount
FROM Users
LEFT JOIN Tweets
ON Users.id = Tweets.UserId
LEFT JOIN Likes
ON Users.id = Likes.UserId
GROUP BY Users.id
ORDER BY UserTweetCount DESC;
I recommend using correlated subqueries for this:
SELECT u.*,
(SELECT COUNT(*)
FROM Tweets t
WHERE u.id = t.UserId
) AS UserTweetCount,
(SELECT COUNT(*)
FROM Likes l
WHERE u.id = l.UserId
) AS UserLikeCount
FROM Users u
ORDER BY UserTweetCount DESC;
As a note: For performance, you want indexes on Tweets(UserId) and Likes(UserId).
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
I want to show all the posts from the people I am following including my own posts too. While it is working as intended, I have a problem: I get the same posts multiple times.
Here is my query:
SELECT posts.id, posts.body, posts.posted_at, posts.postimg, posts.likes, users.`username`
FROM users, posts, followers
WHERE (posts.user_id = followers.user_id OR posts.user_id = :userid)
AND users.id = posts.user_id
AND follower_id = :userid
ORDER BY posts.posted_at DESC;
Can anyone help me? Thank you in advance.
The reason is in this condition:
WHERE (posts.user_id = followers.user_id
OR posts.user_id = :userid)
For every user you are following, you will get all your own posts, thus creating duplicates of own posts.
You should use a UNION (ALL) query. To avoid the full query duplication, you can first select all user IDs in a subquery:
SELECT followers.user_id
FROM followers
WHERE followers.follower_id = :userid
UNION ALL SELECT :user_id
Then join it with your tables:
SELECT posts.id,
posts.body,
posts.posted_at,
posts.postimg,
posts.likes,
users.`username`
FROM (
SELECT followers.user_id
FROM followers
WHERE followers.follower_id = :userid
UNION ALL SELECT :user_id
) uids
JOIN users ON users.id = uids.user_id
JOIN posts ON posts.user_id = uids.user_id
You should try to use:
Select DISTINCT(fields)
From....
Where ...
The DISTINCT will show only one row for every equal results.
I think that your query is working like a cross join.
I hope this helps you, and sorry for my english.
I have three tables:
table: users / columns: user_id, email, username
table: activities / columns: object, type, like_count
table: activities2 / columns: object, target_type, subject, type
The like_count in activities table has no problem and I count all of that with this query:
SELECT SUM(activities.like_count) AS likes, users.user_id, users.email, users.username
FROM activities
INNER JOIN users
ON activities.subject = users.user_id
GROUP BY user_id
But there is another count in activities table which is being inserted(NOT UPDATED) each time some other types of posts liked and I counted them by this query:
SELECT activities.subject, activities.object, COUNT(activities.type) AS likes
FROM activities
INNER JOIN activities2
ON activities.object = activities2.object AND activities2.target_type = 'parent'
WHERE activities2.type LIKE 'like_%'
GROUP BY activities2.subject
BUT the problem starts from here when I want to join them together! I want to count like_count + count of likes that inserted in that table(activities2) that contains string of 'like_' and beside this I want to join the subject(in activities table) which is related to user_id in the other table(users).
My last query is this:
SELECT users.user_id, users.email, users.username, activities.object, COUNT(activities.type)+SUM(activities.like_count) AS likes
FROM activities
INNER JOIN activities2
ON activities.object = activities2.object AND activities2.target_type = 'parent'
INNER JOIN users
ON activities.subject = users.user_id
WHERE activities2.type LIKE 'like_%'
GROUP BY users.user_id
The problem is when joining, it fetches the user information not for the one that I want.
In conclusion I want something like this:
user_id------email-----------------username----------object-------likes
2521---------a#b.com---------------abc---------------9578---------3
5484---------c#d.com---------------def---------------8547---------16
8431---------e#f.com---------------ghi---------------4584---------1
And offcourse the result is this but only likes are correct however columns of user_id, email, username that are in users table NOT!
I was wondering if you would help to fix it. I'm really tired of trying and facing to no result :(
users table data:
user_id-------------email---------------username
1-------------------a#b.com-------------abc
2-------------------c#d.com-------------def
3-------------------e#f.com-------------ghi
activities table data:
object----------type----------------like_count------subject
20--------------like_video----------0---------------1
20--------------like_photo----------0---------------2
33--------------like_music----------0---------------3
33--------------some_other_type-----5---------------6
33--------------some_other_type-----8---------------10
activities2 table data:
object------target_type-----subject-----type
20----------parent----------30----------like_video
21----------owner-----------40----------like_audio
22----------parent----------50----------something_not_start_with_like_
I want:
user_id------email-----------------username----------object-------likes
1------------a#b.com---------------abc---------------9578---------(sum of like_count + count of type which has like_ in first characters)
2------------c#d.com---------------def---------------8547---------(sum of like_count + count of type which has like_ in first characters)
3------------e#f.com---------------ghi---------------4584---------(sum of like_count + count of type which has like_ in first characters)
Consider joining the aggregate queries using derived tables and then run your addition calculation in the outer query. Also, below object column is removed from the second aggregate query's GROUP BY clause but still used in JOIN since you need summation at the subject level.
SELECT u.user_id, u.email, u.username, a.`object`, u.likes + a.likes as `total_likes`
FROM
(SELECT SUM(activities.like_count) AS likes, users.user_id, users.email, users.username
FROM activities
INNER JOIN users
ON activities.subject = users.user_id
GROUP BY user_id, users.email, users.username) u
INNER JOIN
(SELECT activities.subject, COUNT(activities.type) AS likes
FROM activities
INNER JOIN activities2
ON activities.object = activities2.object AND activities2.target_type = 'parent'
WHERE activities2.type LIKE 'like_%'
GROUP BY activities2.subject) As a
ON u.user_id = a.subject
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.