query in mysql with node js - mysql

i am trying to get comments likes and dislike in post but i cant get comments in strings
SELECT p.*, u.full_name as post_author,c.*,l.*, GROUP_CONCAT(c.comment SEPARATOR ',') as comments, GROUP_CONCAT(u3.id SEPARATOR '#') as post_likers FROM post p LEFT JOIN posts_comments c ON c.post_id = p.id LEFT JOIN post_like_dislike l ON l.post_id = p.id LEFT JOIN user u ON u.id = p.user_id LEFT JOIN user u2 ON u2.id = c.user_id LEFT JOIN user u3 ON u3.id = l.user_id GROUP BY p.id
i have tried this query but getting the proper result
.enter image description here
i am getting comments like this but i want comments with user name and comment ..
there are 3 different tables comments post and like
i want to get all comment of a post in post and in string or json formenter image description here
like this .. i am using node JS with mysql

If you want a SQL-only solution, try this
SELECT p.*, u.full_name as post_author,c.*,l.*,
IF(c.id IS NOT NULL, JSON_ARRAYAGG(JSON_OBJECT('id', c.id, 'comment', c.comment)), NULL) AS comments,
IF(u3.id IS NOT NULL, JSON_ARRAYAGG(JSON_OBJECT('id', u3.id)), NULL) AS post_likers
FROM post p
LEFT JOIN posts_comments c ON c.post_id = p.id
LEFT JOIN post_like_dislike l ON l.post_id = p.id
LEFT JOIN user u ON u.id = p.user_id
LEFT JOIN user u2 ON u2.id = c.user_id
LEFT JOIN user u3 ON u3.id = l.user_id
GROUP BY p.id
Note: there are many ORM out there already handle query relationship like this, give it a try.

Related

Mysql query returning too many results

I'm working on a project where I need to check if the user liked the post and then use COUNT() on it, if it gives 0 they haven't if it says 1 they have liked it
I tried using this query
SELECT P.id AS id
, U.username AS username
, P.body AS body
, P.timestamp AS timestamp
, COUNT(L.user_id) AS likes
, COUNT(LD.post_id) AS liked
FROM posts AS P
LEFT JOIN users AS U ON U.id = P.user_id
LEFT JOIN followers AS F ON F.user_id = 'user1'
LEFT JOIN likes AS L ON L.post_id = P.id
LEFT JOIN likes AS LD ON LD.post_id = P.id
AND LD.user_id = 'user1'
WHERE F.following_id = P.user_id
OR P.user_id = 'user1'
GROUP BY P.id
My entrys in my likes table are
UserId|PostId|timestamp
user1 |post1 |time
user2 |post1 |time
My problem is it keeps giving a 2 for the count of LD which shouldn't be possible
*Note: In my code I use :user through PDO I don't actually type the id like that
Edit:
$sql = "SELECT P.id AS id, P.user_id AS userid, U.username AS username, U.name AS name, U.verified AS verified, P.body AS body, P.data AS data, P.timestamp AS timestamp, P.type AS type, P.users AS users, COUNT(L.user_id) AS likes, COUNT(DISTINCT LD.post_id) AS liked FROM posts AS P LEFT JOIN users AS U ON U.id = P.user_id LEFT JOIN followers AS F ON F.user_id = :userid LEFT JOIN likes AS L ON L.post_id = P.id LEFT JOIN likes AS LD ON LD.post_id = P.id AND LD.user_id = :userid WHERE F.following_id = P.user_id OR P.user_id = :userid GROUP BY P.id";
$results = DB::query($sql, array(':userid' => $user_id));
I then loop through the results and format them into json
Can you try adding a DISTINCT keyword on the COUNT function for liked column?
COUNT(DISTINCT LD.post_id) AS liked
Most likely the joins are causing the likes table to be duplicated. Thus, we'll only count the unique posts (by post_id) using DISTINCT.

How to get comments and the comments' replies out of table

I have a comments table.
I want to get the comments and replies out of the table to display them like this. I am just looking for a query so I can do something like this
What I Did
Query I used
SELECT c.post_id, c.id AS comment_id, c.user_id, users.username, c.created, c.comment, r.id AS reply_id, r.parent_comment_id, r.created, r.comment AS reply, r.user_id AS reply_user_id, r_user.username as reply_username FROM (comments c) LEFT JOIN comments r ON c.id = r.parent_comment_id LEFT JOIN users ON c.user_id = users.id LEFT JOIN users as r_user ON r.user_id = r_user.id WHERE r.id OR c.post_id IS NOT NULL ORDER BY parent_comment_id ASC;
Maybe something like this:
SELECT
c.comment,
IFNULL(r.comment, '') reply
FROM
comments c
LEFT JOIN comments r
ON c.id = r.parent_comment_id
WHERE
c.parent_comment_id is null

Get results when where value is 'grade' or where it doesn't exist

I have a wordpress site that is used to store student grades on various lessons (from the quizzes on the site). I am trying to create a query that will pull out all of the lessons for all students in a certain group (using buddypress groups) and the students grades in each lesson.
I have created this query:
SELECT u.display_name, p.post_title, cm.meta_value
FROM wp_users u
JOIN wp_bp_groups_members gm
ON u.ID = gm.user_id
JOIN wp_comments c
ON u.ID = c.user_id
JOIN wp_commentmeta cm
ON c.comment_ID = cm.comment_id
JOIN (SELECT * FROM wp_posts WHERE post_type LIKE 'lesson') p
ON c.comment_post_id = p.ID
WHERE gm.group_id = 4 AND cm.meta_key LIKE 'grade'
This currently returns all the grades for all students in a group in the lessons they have attempted the test. However it does not return any lessons they have not attempted the test in, which I need still.
Just to be clear: lessons are posts, grades are meta_values in a record with a meta_key of 'grades'. These are stored as comments, and comment_meta.
I hope this is all clear and you can help. Thanks.
After Ollie Jones help I made this:
SELECT u.display_name, p.post_title, IFNULL(cm.meta_value,'--nothing--') grade
FROM wp_users u
JOIN wp_comments c
LEFT JOIN wp_commentmeta cm
ON c.comment_ID = cm.comment_id AND cm.meta_key = 'grade'
JOIN wp_bp_groups_members gm
ON u.ID = gm.user_id
JOIN wp_posts p
ON c.comment_post_id = p.ID
WHERE gm.group_id = 4 AND p.post_type LIKE 'lesson'
Which almost works but returns all student grades, not just the ones in the group (though it only gives the one name of the student in the group).
This is the familiar key/value store problem, that comes up with commentmeta, postsmeta, and usermeta. When you JOIN two tables and the left one might not have a corresponding row, you need to use LEFT JOIN. When the left one is a key/value table, you need to adjust the ON condition accordingly. Finally, when you LEFT JOIN two tables and there's no matching row in it it, you get back NULLs for those columns, so you must allow for that.
So this kind of SQL pattern will do the trick for you
SELECT whatever, IFNULL(cm.meta_value,'--nothing--') grade
FROM whatever
LEFT JOIN wp_comments c ON whatever.id = c.user_id
LEFT JOIN wp_commentmeta cm ON c.comment_id = cm.comment_id
AND cm.meta_key = 'grade'
JOIN whatever
Is there a user_id in your comments table? I dont see where you joined which user posted which comment. So when you join the group_members to the users table, you are specifying which users to show, but since you are not joining on user id when you join to your comments table, it will show all the comments for all the users. Im not sure if this will work for your table, but try:
SELECT u.display_name, p.post_title, IFNULL(cm.meta_value,'--nothing--') grade
FROM wp_users u
LEFT JOIN wp_comments c
JOIN wp_commentmeta cm
ON c.comment_ID = cm.comment_id AND cm.meta_key = 'grade'
JOIN wp_bp_groups_members gm
ON c.user_ID = gm.user_id
ON u.user_id = c.user_id
JOIN wp_posts p
ON c.comment_post_id = p.ID
WHERE gm.group_id = 4 AND p.post_type LIKE 'lesson'
Hope this helps!

join 3 sql tables and make nested query

So I have 3 tables called comments, users and posts.
I want to get
the "score" from comments
the "user reputation" for users by doing the left join between comments and users with c.user_id = u.id
get the "tags" from posts table by doing a left join between comments and posts on c.post_id = p.id.
BUT there is a trick here the tags should be based on the type of the posts (p.post_type_id).
So if the id = 1 then that means we have a "question" as a post and simply retrieve tag
Else if the id = 2 then that means we have an answer and to get the tag we have to look at its parent_id from posts table.
I tried to use WHERE, CASE, nested IF, and nested SELECT but all threw syntax errors
Finally, I tried to do the following but I got an empty result
SELECT c.score,
COALESCE (u.reputation) reputation,
COALESCE (p.tags) tags
FROM comments c
LEFT JOIN users u
ON c.user_id = u.id
LEFT JOIN posts p
ON (c.post_id = p.id AND p.post_type_id = 1) OR (c.post_id = p.id AND p.post_type_id = 2 )
WHERE (p.id = p.parent_id)
So how can I have the tags based on the two types ?
Just quick guess:
http://sqlfiddle.com/#!9/a1cc3/1
SELECT c.score,
u.reputation reputation,
IF(p.post_type_id=1,p.tags,
IF(p.post_type_id=2,parents.tags,'UNKNOWN POST TYPE')
) tags
FROM comments c
LEFT JOIN users u
ON c.user_id = u.id
LEFT JOIN posts p
ON c.post_id = p.id
LEFT JOIN posts parents
ON parents.id = p.parent_id
UPDATE Here is Postgres variant:
http://sqlfiddle.com/#!15/a1cc3/2
SELECT c.score,
u.reputation,
CASE p.post_type_id
WHEN 1 THEN p.tags
WHEN 2 THEN parents.tags
ELSE 'UNKNOWN POST TYPE'
END tags
FROM comments c
LEFT JOIN users u
ON c.user_id = u.id
LEFT JOIN posts p
ON c.post_id = p.id
LEFT JOIN posts parents
ON parents.id = p.parent_id

Mysql query help. I need to make sure atleast one record is returning

I have a query that I know it should atleast return one row. How can i modify my follow query to make sure that album returns data. thanks for any help.
Query Here. I know that Album has a row and I need to return it.
select distinct p.*,
a.ID as parentalbumid,a.CreatorID as albumcreatorid,a.AlbumName,a.AlbumDescription,a.AlbumDefaultImageURL,a.Private,a.DateCreated,a.AdultContent,a.PasswordProtected,a.AllowTags,a.TypeID,a.AlbumAutoID,
mainuser.Username as mainuserusername,mainuser.ID as mainuserid,mainuser.PictureUrl as mainuserpictureurl,
c.ID as commentID,c.PhotoID as commentphotoid,c.OutputMessage,c.CommentDate,
t.ID as tagID,t.PhotoID as tagphotoid,t.UserID,t.TextTag,t.LeftLocation,t.TopLocation,
u.ID as userid,u.Username,u.FirstName,u.LastName,u.PictureUrl
from photos p
inner join albums a on a.ID = p.AlbumID
inner join users mainuser on mainuser.ID = p.UserID
left join comments c on c.PhotoID = p.ID
left join tags t on t.PhotoID = p.ID
left join users u on u.ID = c.CommentBy
where a.AlbumAutoID = 3
order by p.DateUploaded desc;
Use only LEFT JOINs (and put the table albums as the first table of your FROM):
select distinct p.*,
a.ID as parentalbumid,a.CreatorID as albumcreatorid,a.AlbumName,a.AlbumDescription,a.AlbumDefaultImageURL,a.Private,a.DateCreated,a.AdultContent,a.PasswordProtected,a.AllowTags,a.TypeID,a.AlbumAutoID,
mainuser.Username as mainuserusername,mainuser.ID as mainuserid,mainuser.PictureUrl as mainuserpictureurl,
c.ID as commentID,c.PhotoID as commentphotoid,c.OutputMessage,c.CommentDate,
t.ID as tagID,t.PhotoID as tagphotoid,t.UserID,t.TextTag,t.LeftLocation,t.TopLocation,
u.ID as userid,u.Username,u.FirstName,u.LastName,u.PictureUrl
from albums a
left join photos p on a.ID = p.AlbumID
left join users mainuser on mainuser.ID = p.UserID
left join comments c on c.PhotoID = p.ID
left join tags t on t.PhotoID = p.ID
left join users u on u.ID = c.CommentBy
where a.AlbumAutoID = 3
order by p.DateUploaded desc;