I need to do the following:
Select the latest posts (last 10 for example) in post table
Join the user info from users table
Join the media avatar for user in media table where type = avatar and media_author = user.id
Join the media of the post (from 1 to 4 for every single post)
in addiction next I need to filter post of friends and post with preferred hashtag of the user that retrieve the data. I think that all this cannot be done in one single query, right?
In the final solution I need to:
get the post
score and order the posts based on some rule (is friends? have hashtag? etc..)
serve the ordered post with user info and posts info (like count, etc..)
Maybe the better solution is:
only select the post, and for each post do two query to retrieve user and media data?
For now this is the queries that I use for the single post:
SELECT posts.id, posts.user_id, posts.privacy, posts.type, posts.published, posts.language,
posts.content, posts.date, posts.entity_map, users.username, media.media_url
FROM posts
LEFT JOIN (SELECT * FROM users) users
ON (users.id = posts.user_id )
LEFT JOIN (SELECT * FROM media ORDER BY media.id DESC) media
ON (media.media_author = posts.user_id AND media.media_type = 'avatar')
WHERE posts.id = ?
SELECT * FROM media WHERE media_parent = ?
Have sense to do 20 query to retrieve a list of 10 posts?
here the tables structure:
tbl posts
id
content
date
entity_map
language
privacy
published
raw_content
type
user_id
tbl users
id
name
username
tbl media
id
media_author
media_date
media_parent
media_status
media_type
media_url
tbl like/love
te be defined, but I think a table with:
id
id_from
id_to
type (like/love/other)
This will get you the latest 10 posts.
SELECT posts.id, posts.user_id, posts.privacy, posts.type, posts.published, posts.language,
posts.content, posts.date, posts.entity_map, users.username, media.media_url
FROM posts
LEFT JOIN (SELECT * FROM users) users
ON (users.id = posts.user_id )
LEFT JOIN (SELECT * FROM media ORDER BY media.id DESC) media
ON (media.media_author = posts.user_id AND media.media_type = 'avatar')
Order By post.date desc
limit 10
To fetch the media you have to make query for each post. As, sql doesn't facilitate the reference like mongodb.
Related
I want to get all my posts data to show it on my webpage with this SELECT. I have my table posts that contains most of the posts (+ replies) data and a table social that tracks who views and likes it(each like is a new row).
Normally I can get the username, post time, content... but I'm struggling to get the number of views the post gets, the number of likes, and the number of replies in the same SELECT. My base SELECT looks like this:
SELECT posts.username, posts.time, cat.cat_name,
posts.title, posts.content, posts.reply,
posts.user_file, posts.audio, social.id,
social.views, social.likes
FROM posts
LEFT JOIN user on posts.user_id = user.id
LEFT JOIN cat ON posts.cat_id = cat.id
LEFT JOIN social ON posts.id = social.post_id
If I wanted to get the number of comments per post I would use
(if the value inside reply is 0 it's a post if it's a reply it contains the post id it's referring to):
SELECT COUNT(*) AS `comments` FROM posts GROUP BY reply
/* this returns an error: SQL Error (1242): Subquery returns more than 1 row */
And I would get the number of likes and views like this:
SELECT MAX(social.views) AS views FROM social GROUP BY post_id
SELECT social.likes FROM social WHERE social.id = (SELECT MAX(social.id) FROM social GROUP BY post_id
But if I use it together in the earlier SELECT it just fills every row with the same number. Example:
... posts.audio, social.id, (SELECT MAX(social.views) AS views FROM social GROUP BY post_id) FROM posts ...
This just fills every row even if it shouldn't have views with 25 (correct value for 1 specific row but wrong for everything else).
What would be a proper way of making a bigger SELECT like this?
Not sure if it matters but I am using it with a MySQL module in NodeJS.
Try this way
SELECT posts.username, posts.time, cat.cat_name,
posts.title, posts.content, posts.reply,
posts.user_file, posts.audio,
COUNT(social.views), COUNT(social.likes)
FROM posts
LEFT JOIN user on posts.user_id = user.id
LEFT JOIN cat ON posts.cat_id = cat.id
LEFT JOIN social ON posts.id = social.post_id
GROUP BY
posts.username, posts.time, cat.cat_name,
posts.title, posts.content, posts.reply,
posts.user_file, posts.audio
This is the closest I've gotten to SELECTing everything in one query but I still don't have a way of counting the number of comments:
SELECT posts.username, posts.time, cat.cat_name,
posts.title, posts.content, posts.reply,
posts.user_file, posts.audio,
social.views, social.likes
FROM posts
LEFT JOIN user on posts.user_id = user.id
LEFT JOIN cat ON posts.cat_id = cat.id
LEFT JOIN social ON posts.id = social.post_id
WHERE social.likes IN (SELECT social.likes FROM social
WHERE social.id IN (SELECT MAX(social.id)
FROM social GROUP BY post_id))
GROUP BY social.post_id
HAVING posts.reply = 0
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 want to join two tables and return a random field from the second table because there are multiple matches when joining.
For example. I have a users table and a user_posts table. I want to select each user's id, and a random post id and the post's message that they have in the user_posts table. Each user can have multiple posts in the user_posts table.
This answer explains what I'm trying to do, but it's not working. Here's my query:
SELECT user_id, post_id, message FROM (
SELECT users.id AS user_id, user_posts.id AS post_id, message
FROM users INNER JOIN user_posts ON users.id = user_id
ORDER BY RAND()
) AS a GROUP BY user_id
For testing, I added two rows in the user_posts table for user with id of 1 but it's retrieving the same post every time.
using cross apply to get random one post and join to users to display
select u.id,RandomPostbyUser.*
from users u
cross apply (
SELECT user_posts.id AS post_id, message
FROM users u1 INNER JOIN user_posts ON u1.id = u.id
order by RAND()
LIMIT 1) RandomPostbyUser
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.
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.