I have a query that I am using to join two tables (posts, relations) to return posts from users you are following (r.status= 1) or friends (r.status= 2) with. But then also omitting the posts where the post privacy is private (p.privacy= 2) and the current relationship (r.status= 1).
Here is my query:
$user_id= 1;
$posts_query= "
SELECT DISTINCT post_id, user_id, story, photo, link, collection_id, privacy, date, type
FROM posts p
JOIN relations r ON p.user_id = r.recipient
AND (r.sender = '".$user_id."')
AND NOT (r.status = 1 AND p.privacy = 2)
ORDER BY p.post_id DESC;
";
Now the only problem with this query is that It omits your own personal posts.
The query for that would be:
$your_posts_query= "SELECT * FROM posts WHERE user_id= '".$user_id."' ORDER BY p.post_id
DESC";
Now, This doesn't allow me aggregate all of the posts together. Yours, and the ones from your friends and the people you are following.
How can I make it so that my first query also incorporates what my second query does?
$user_id= 1;
$posts_query= "
SELECT DISTINCT post_id, user_id, story, photo, link, collection_id, privacy, date, type
FROM posts p
JOIN relations r ON p.user_id = r.recipient
AND (r.sender = '".$user_id."' OR p.user_id= '".$user_id."')
AND NOT (r.status = 1 AND p.privacy = 2)
ORDER BY p.post_id DESC;
";
Combine the two together to get as one result set
$posts_query= "
SELECT post_id, user_id, story, photo, link, collection_id, privacy, date, type
FROM posts WHERE user_id= '".$user_id."'
union
SELECT DISTINCT post_id, user_id, story, photo, link, collection_id, privacy, date, type
FROM posts p
JOIN relations r ON p.user_id = r.recipient
AND (r.sender = '".$user_id."')
AND NOT (r.status = 1 AND p.privacy = 2)
ORDER BY p.post_id DESC;
";
Related
Ok, so this is not a new problem to me but since sophisticated SQL queries is not among my best talents I would typically break it apart. Still, I'm pretty sure a single query is possible and this time around I feel like doing it right but I simply can't put my finger on it. The following is as far as I could go:
SELECT forums.forum, forums.description, topics.forum_id,
(SELECT COUNT(id) FROM topics WHERE forum_id = forums.id) AS num_topics,
(SELECT COUNT(id) FROM posts WHERE topic_id = topics.id) AS num_posts,
MAX(posts.id) AS last_post
FROM forums
LEFT JOIN topics ON topics.forum_id = forums.id
LEFT JOIN posts ON posts.topic_id = topics.id
LEFT JOIN users ON users.id = posts.author_id
So I select forum id, forum name, short description and forum id aqcuired from topics table because the column name is unique by default. Then I use subqueries to count the sum total of topics and posts per forum (is there any other way to do it?). And then comes the most tricky part. I can get the last post per forum (MAX(post.id)) but try as I might I can't get the topic id and name for it, as well as the post author, which I never even got close to. Doing something like (SELECT topic_id FROM posts WHERE id = last_post) is not working, of course, and I don't understand why.
This will not be quick
SELECT forums.
forum, forums.description, topics.forum_id,
(SELECT COUNT(id) FROM topics WHERE forum_id = forums.id) AS num_topics,
(SELECT COUNT(id) FROM posts WHERE topic_id = topics.id) AS num_posts,
MAX(posts.id) AS last_post,
(SELECT topic_id FROM posts ORDER BY id DESC LIMIT 1) LAst_topic_id,
(SELECT topic_name FROM topics WHERE id = (SELECT topic_id FROM posts ORDER BY id DESC LIMIT 1)) LAst_topic_name
FROM forums
LEFT JOIN topics ON topics.forum_id = forums.id
LEFT JOIN posts ON posts.topic_id = topics.id
LEFT JOIN users ON users.id = posts.author_id
Or if the last id is not really the last id from the post tables
SELECT
forum,description,forum_id,num_topics,num_posts,last_post,
(SELECT topic_id FROM posts WHERE id = last_post) LAst_topic_id,
(SELECT topic_name FROM topics WHERE id = (SELECT topic_id FROM posts WHERE id = last_post)) LAst_topic_name
FROM
(SELECT
forums.forum, forums.description, topics.forum_id,
(SELECT COUNT(id) FROM topics WHERE forum_id = forums.id) AS num_topics,
(SELECT COUNT(id) FROM posts WHERE topic_id = topics.id) AS num_posts,
MAX(posts.id) AS last_post
FROM forums
LEFT JOIN topics ON topics.forum_id = forums.id
LEFT JOIN posts ON posts.topic_id = topics.id
LEFT JOIN users ON users.id = posts.author_id) t1;
I'm doing a favorite system which allow users to save the posts to their page.
The tables I'm using are:
saved_posts table which contain 3 columns (painned_id``user_id``post_id)
users which contain (user_id, frist_name, last_name, username, email, password, user_website, user_avatar)
Finally posts table (post_id, user_id, post_author, category_id, post_date, post_image, post_avatar, user_website, post_keywords, post_content)
The my sql code I'm using to get the saved posrt
SELECT * FROM posts INNER JOIN saved_posts
ON saved_posts.post_id =
posts.post_id INNER JOIN users on saved_posts.user_id = users.user_id WHERE
saved_posts.user_id = users.user_id AND saved_posts.post_id = posts.post_id
The problem is that the saved posts from one user appears for other user as if they saved them as well.
Shouldn't you filter your answer with a WHERE condition? Otherwise it is just finding all posts that any user shared EVER.
SELECT * FROM posts
INNER JOIN saved_posts
ON saved_posts.post_id = posts.post_id
INNER JOIN users
ON saved_posts.user_id = users.user_id
WHERE users.user_id = :wanted_user_id
Don't forget to bind wanted_user_id.
If I understood the question correctly, the task is to select all the posts which of the users
SELECT * FROM posts p
INNER JOIN saved_posts sp ON p.post_id = sp.post_id
and sp.user_id = u.user_id
INNER JOIN users u on p.user_id = u.user_id
Right now I'm using UNION to get records from multiple tables, which is fine. But I want to include the author for the specific post.
$run = mysql_query("
SELECT article_id AS id, title, smalldesc, hits, coverpic AS picture, timestamp, member_id AS mid, type FROM articles
UNION
SELECT video_id AS id, titel, smalldesc, hits, ytid AS picture, timestamp, member_id AS mid, type FROM videos
UNION
SELECT picture_id AS id, title, smalldesc, hits, coverpic AS picture, timestamp, member_id AS mid, type FROM pictures ORDER BY timestamp DESC LIMIT ".$postnumbers." OFFSET ".$offset."
") or die(mysql_error());
I want the following select to be a part of the code above:
SELECT member_id, picture, fname, lname FROM members WHERE member_id='mid'
I want to get the member from each post, so I can print out who made the post.
You've got, as you asked, to join the members table to the three part queries of the UNION:
SELECT
a.article_id AS id,
a.title,
a.smalldesc,
a.hits,
a.coverpic AS picture,
a.timestamp,
a.member_id AS mid,
a.type,
m.picture,
m.fname,
m.lname
FROM
articles a
INNER JOIN
members m
ON
a.member_id = m.member_id
UNION
SELECT
v.video_id,
v.titel,
v.smalldesc,
v.hits,
v.ytid AS picture,
v.timestamp,
v.member_id AS mid,
v.type
m2.picture,
m2.fname,
m2.lname
FROM
videos v
INNER JOIN
members m2
ON
v.member_id = m2.member_id
UNION
...
to get this information.
Some background:
I'm developing kind of social network.
There is DB with next tables:
users(user_id, user_name, password, etc.)
posts(post_id, user_id, post_text, post_data, etc.)
followings(relationship_id, follower_id, following_id, added_date_time)
likes(like_id, user_id, post_id, added_date_time)
comments(comment_id, user_id, post_id, comment_text, added_date_time)
The question is:
How can I implement query which would fetch information about what my followings(people I follow) have did recently (e.g. someone liked/commented something) and order this array of info by date_time?
Can I make it using one query? Or I'll have to make multiple queries and handle all this stuff in PHP by myself?
What is the best approach?
You can normalize the output in a select union like this one
SELECT t.type, t.user_id, u.user_name, t.type_id, t.post_id, t.text, t.added_date_time
FROM (
SELECT 'posts' as type, p.user_id, p.post_id as type_id, p.post_id, post_text as text, p.added_date_time
FROM posts p
JOIN followings f ON (f.following_id = p.user_id)
WHERE f.follower_id = #user
UNION
SELECT 'comments' as type, c.user_id, c.comment_id as type_id, c.post_id, comment_text as text, c.added_date_time
FROM comments c
JOIN followings f ON (f.following.id = c.user_id)
WHERE f.follower_id = #user
UNION
SELECT 'likes' as type, l.user_id, l.like_id as type_id, l.post_id, post_text as text, l.added_date_time
FROM likes l
JOIN followings f ON (f.following.id = c.user_id)
JOIN posts p ON (l.post_id = p.post_id)
WHERE f.follower_id = #user
) as t
JOIN users u ON (t.user_id = u.user_id)
ORDER BY added_date_time DESC;
So you can get all the data in only one query.
I hope it works fine for you.
You have to seperate at least the queries for likes and comments, since the result set is different.
Otherwise your query would look e.g. like:
SELECT comment_id,comment_text,added_date_time FROM comments WHERE user_id IN (SELECT following_id FROM followings WHERE follower_id={{USER_ID_FROM_USER}}) ORDER BY added_date_time
This will get you the comments from people which are followed by {{USER_ID_FROM_USER}} ordered by date.
I`m trying to extract the activity of a user with a single query. I need to do it with one single query so I can use zend paginator.
I have 5 tables: users, replies, threads, wiki_articles and wiki_article_revisions. Each table has 2 common columns created_by and created_on.
I've tried using left join but I think what it returns is not correct and I'm unable to order all activity by created_on
Here is the join I've tried:
SELECT * FROM `users` u
LEFT join `replies` r ON u.id = r.created_by
LEFT join `threads` t ON u.id = t.created_by
LEFT join `wiki_articles` wa ON u.id = wa.created_by
LEFT join `wiki_article_revisions` war ON u.id = war.created_by
WHERE (u.`name` = 'CGeorges')
My thought process was wrong. I should have used UNION for this, like:
(SELECT id, name, created_on FROM users WHERE id = 1)
UNION
(SELECT id, name, created_on FROM threads WHERE created_by = 1)
UNION
(SELECT id, content, created_on FROM replies WHERE created_by = 1)
UNION
(SELECT id, title, created_on FROM wiki_articles WHERE created_by = 1)
ORDER by created_on DESC