I'm working on a project where I have posts that can be reposted to the pure style of twitter (retweets). The posts are saved in a table "posts" (id, userid, title, content, date) and the reposts are saved in another table "reposts" (postid, userid, date). I need to show posts and reposts of a user arranged chronologically and in a descending order.
So far what I have been able to do is show both tables but the reposts are shown ordered with the creation date of the post, not with the date of the repost. If I repost a post from 2 years ago, I want the post to be shown now (reposts date), and not ordered with the posts from 2 years ago (posts date).
This is my query:
SELECT * FROM (SELECT p.* FROM post AS p WHERE userid='$id' UNION SELECT p.* FROM post AS p WHERE p.id IN (SELECT postid FROM repost WHERE userid='$id')) a ORDER BY date DESC
Join reposts and posts and pick the columns you want from each table.
SELECT *
FROM (SELECT p1.postid,
p1.userid,
p1.title,
p1.content,
p1.date
FROM posts p1
WHERE p1.userid = ?
UNION ALL
SELECT r1.postid,
r1.userid,
p2.title,
p2.content,
r1.date
FROM reposts r1
INNER JOIN posts p2
ON p2.postid = r1.postid
WHERE r1.userid = ?) x
ORDER BY x.date DESC;
Related
Currently I have the following database:
Table 1: Customer_Stores
unique_id
page_address
date_added
guide_summary
user_name
cover_photo
guide_title
Table 2: Customer_Stories_Likes
story_id
likex
The 'like' column in the second table contains a 1 or a 0 to indict whether or not a user has liked a post.
What I'd like to do is join these two tables together with 'post_id' and count all of the 'likes' for all the posts based on post_id and order these by how many likes each post got. Is this possible with a single statement? or is it better to use a Count(*) to first determine how many likes each post has?
Yes, it's possible, but you don't need an inner join, because you don't actually need the posts table to do it.
SELECT post_id, count(like) AS post_likes
FROM likes
WHERE like = 1
GROUP BY post_id
ORDER BY post_likes DESC
If you need other information from the posts table as well, you could join it to a subquery that gets the like counts.
SELECT posts.*, like_count
FROM
posts LEFT JOIN
(SELECT post_id, count(like) AS like_count
FROM likes
WHERE like = 1
GROUP BY post_id) AS post_likes
ON posts.post_id = post_likes.post_id
ORDER BY like_count DESC
I used LEFT JOIN rather than INNER JOIN, you can use INNER JOIN if you don't want to include posts with no likes.
Here is my comments table:
|id(int) | user_id(int) | post_id(int) | text(char)|
----------------------------------------------------
| | | | |
I want to calculate how many users has comments to each post
and how many comments do every post have.
I've already done the latter one as following:
select count(*) from comments group by post_id;
but how about the first one? any idea?
How many post do exists?
select count(1) from posts
How many posts each user have commented?
select user_id, count(distinct post_id)
from comments
group by user_id
Wich users have commented every post?
select user_id
from comments
group by user_id
having count(distinct post_id) = (select count(1) from posts)
How many users have commented every post?
select count(1)
from (
select user_id
from comments
group by user_id
having count(distinct post_id) = (select count(1) from posts)
) sub
Edited answer
How many users have commented each post with comments
select post_id, count(distinct user_id) as users_count
from comments
group by post_id
Original answer
How many users has comments to every post
I don't see your posts table so I'll assume it exists.
select count(*) AS users_with_comments_to_every_post
from (
select count(distinct post_id) as count_comments
from comments
group by user_id
) c
inner join ( select count(*) AS count_posts from posts ) p on
c.count_comments = p.count_posts
We need the posts table to involve posts that have no comments.
How many comments do every post have
select post_id, count(*)
from comments
group by post_id
How many users has comments to every post
SELECT post_id, count(distinct user_id) as user_count
FROM comments
GROUP BY post_id
This way you are avoiding subqueries.
I am currently trying to retrieve the latest posts along with their related posts (x number for each post). I have the following query in hand:
SELECT id, title, content
(SELECT GROUP_CONCAT(title) FROM posts -- Select title of related posts
WHERE id <> p.id AND id IN (
SELECT p_id FROM tagsmap -- Select reletad post ids from tagsmap
WHERE t_id IN (
SELECT t_id FROM tagsmap -- Select the tags of the current post
WHERE p_id = p.id)
) ORDER BY id DESC LIMIT 0, 3) as related
FROM posts as p ORDER BY id DESC LIMIT 5
My database structure is simple: A posts table. A tags table. And a tagsmap table where I associate posts with tags.
This query works fine (though I don't know its performance since I don't have many rows in the tables -- Maybe an explain could help me but that's not the case right now).
What I really need is to retrieve the ids of the related posts along with their titles.
So I'd like to do SELECT GROUP_CONCAT(title), GROUP_CONCAT(id), but I know that will result in an error. So what is the best way to retrieve the id along with the title in this case? I do not want to rewrite the whole subquery to just retrieve the id. There should be another way.
EDIT
SELECT p1.id, p1.title, p1.content,
group_concat(DISTINCT p2.id) as 'P IDs',
group_concat(DISTINCT p2.title) as 'P titles'
FROM posts as p1
LEFT JOIN tagsmap as tm1 on tm1.p_id = p1.id
LEFT JOIN tagsmap as tm2 on tm2.t_id = tm1.t_id and tm1.p_id <> tm2.p_id
LEFT JOIN posts as p2 on p2.id = tm2.p_id
GROUP BY p1.id
ORDER BY p1.id desc limit 5;
At the end this is the query that I've used. I removed the Where clause because it is unnecessary and used LEFT JOIN rather that JOIN because otherwise it would ignore the posts without tags. And finally added DISTINCT to group_concat because it was concatenating duplicate rows (If for example a post had multiple common tags with a related post it would result in a duplicate concatenation).
The query above works perfectly. Thanks for all.
Okay - this will work, and it has the added advantage of eliminating the sub queries (which can slow you down when you get lots of records):
SELECT p1.id, p1.title, p1.content,
group_concat( p2.id) as 'P IDs',
group_concat( p2.title) as 'P titles'
FROM posts as p1
JOIN tagsmap as tm1 on tm1.p_id = p1.id
JOIN tagsmap as tm2 on tm2.t_id = tm1.t_id and tm1.p_id <> tm2.p_id
JOIN posts as p2 on p2.id = tm2.p_id
WHERE p2.id <> p1.id
GROUP BY p1.id
ORDER BY p1.id desc limit 5;
What we're doing here is selecting what you want from the first version of posts, joining them to the tagsmap by their post.id, doing a self join to tagsmap by tag id to get all the related tags, and then joining back to another posts (p2) to get the posts that are pointed to by those related tags.
Use GROUP BY to discard the dups from all that joining, and you're there.
like this?
SELECT id, title, content
(SELECT GROUP_CONCAT(concat(cast(id as varchar(10)), ':', title)) FROM posts -- Select title of related posts
WHERE id <> p.id AND id IN (
SELECT p_id FROM tagsmap -- Select reletad post ids from tagsmap
WHERE t_id IN (
SELECT t_id FROM tagsmap -- Select the tags of the current post
WHERE post_id = p.id)
) ORDER BY id DESC LIMIT 0, 3) as related
FROM posts as p ORDER BY id DESC LIMIT 5
I have several mysql tables like this:
blogs
entry_id
member_d
articles
entry_id
member_d
posts
entry_id
member_d
I want to count the total entries by a specific member. I currently have this (while only using 3 tables for this example, there is in fact about 10 - 20 tables all structured the same):
SELECT COUNT('member_id') FROM blogs WHERE member_id=3 LIMIT 1;
SELECT COUNT('member_id') FROM articles WHERE member_id=3 LIMIT 1;
SELECT COUNT('member_id') FROM posts WHERE member_id=3 LIMIT 1;
You see the repetition? Is there any way of condensing that down to 1 query for example (doubt this works):
SELECT COUNT(blogs.'member_id') as total_blogs,
COUNT(articles.'member_id') as total_articles,
COUNT(posts.'member_id') as total_posts
FROM blogs,articles,posts WHERE member_id=3 LIMIT 1;
P.S. Tried searching stackoverflow and google but keep getting things about using COUNT(*) or using groups, etc...
This Works,
SELECT
(SELECT COUNT('member_id') FROM blogs WHERE member_id=3) as total_blogs,
(SELECT COUNT('member_id') FROM articles WHERE member_id=3) as total_articles,
(SELECT COUNT('member_id') FROM posts WHERE member_id=3) as total_posts
and gives you all info in only one record
SELECT COUNT(*) FROM(
SELECT member_id FROM blogs
UNION ALL
SELECT member_id FROM articles
UNION ALL
SELECT member_id FROM posts
) AS activity
WHERE member_id=3
GROUP BY member_id
Sqlfiddle demonstration: http://sqlfiddle.com/#!2/366bd/2
Just for the record, I add here a second solution that admit multiple selection of IDs in a single query
SELECT m.member_id,
COALESCE(blogs.total_blogs,0) as total_blogs,
COALESCE(articles.total_articles,0) as total_articles,
COALESCE(posts.total_posts,0) as total_posts
FROM members m -- I guess this table exists
LEFT JOIN (SELECT member_id, COUNT('member_id') as total_blogs FROM blogs GROUP BY member_id) as blogs on m.member_id = blogs.member_id
LEFT JOIN (SELECT member_id, COUNT('member_id') as total_articles FROM articles GROUP BY member_id) as articles on m.member_id = articles.member_id
LEFT JOIN (SELECT member_id, COUNT('member_id') as total_posts FROM posts GROUP BY member_id) as posts on m.member_id = posts.member_id
where m.member_id in (3,4,5)
fiddle here
SELECT
*, (SELECT SUM(rating) FROM votes WHERE votes.postId = posts.id) AS rating
FROM posts
WHERE rating > 10
There are multiple entries in my table where the sum of the ratings in votes with the corresponding post ID is greater than 10, but this query is not returning any results. Why?
Here is the relevant portion of my database structure:
TABLE posts
- id
TABLE votes
- postId
- rating
Any help would be greatly appreciated.
You need to name the subquery column, like this
SELECT * FROM
(SELECT sum(rating) as rating_sum, * FROM posts) AS rating
INNER JOIN posts on posts.id = rating.id
WHERE rating.rating_sum>10
try this.
SELECT posts.*, (select SUM(rating) as totalRating
from votes
where votes.postid = posts.id) as totalRating
FROM posts
WHERE totalRating > 10