MySQL order by before group by did not work - mysql

I have two tables
users
user_id | name
1 | John
2 | Jess
user_data (in_out - 1 indicate in, 0 indicate out)
id | user_id | in_time | out_time | in_out
1 | 1 | 2019-05-14 09:15:32 | 2019-05-14 10:45:32 | 0
2 | 1 | 2019-05-15 10:15:32 | 0000-00-00 00:00:00 | 1
3 | 2 | 2019-05-16 11:15:32 | 2019-05-16 12:15:32 | 0
I want to get latest entries of each user, but group by and order by did not work well.
First I tried following way, but this is not give latest records (I want to get record id 2 and 3 from user_data table, but it returns record id 1 and 3)
SELECT *, user.user_id as user_key
FROM user
LEFT JOIN user_data ON user_data.user_id = user.user_id
GROUP BY user_data.user_id ORDER BY user_data.id DESC
Secondly I tried following way, I wrote this query following an answer of stackoverflow, but it did not work.
SELECT *, user.user_id as user_key
FROM user
LEFT JOIN
(
SELECT MAX(user_data.id) as max_record_id, user_data.user_id
FROM user_data
GROUP BY user_data.user_id
) u2 ON u2.user_id = user.user_id
GROUP BY user_data.user_id ORDER BY user_data.id DESC
Someone please help me to solve this issue. Thank You

You can try using a correlated subquery
SELECT *, user.user_id as user_key
FROM user
LEFT JOIN user_data u2 ON u2.user_id = user.user_id
where u2.id in (select MAX(u3.id) from user_data u3 where u2.user_id=u3.user_id)
ORDER BY u2.id

Related

How to optimize SQL query more?

First at all i am nood into SQL thing, Now i am working on a class project where
I have some tables like
Table user
user_id | username | name
1 | nihan | Nihan Dip
2 | dip | Meaw ghew
more | more | more
Table Friend
you | friend_id
1 | 2
1 | 27
2 | 9
more | more
Table Follow
user_id | follows
1 | 99
7 | 34
Table post
post_id | user_id | type | content | post_time
1 | 1 | text | loren toren | timestamp
2 | 2 | text | ipsum | timestamp
Now i want to get post by users friend and who he follows and offcourse his so i made this SQL
SELECT
username, name,content, post_time
FROM
post
INNER JOIN
user ON user.user_id = post.user_id
WHERE
post.user_id IN (SELECT
friend_id
FROM
friend
WHERE
you = 1
UNION ALL
SELECT
follows
FROM
follow
WHERE
user_id = 1)
OR post.user_id = 1
ORDER BY post_time DESC
LIMIT 10
this query works just fine. I just wanted to know is there anymore optimization could be done? Then how? Please teach me :)
Instead of using IN try it with JOIN add add few more indexes.
SELECT DISTINCT u.name, u.username,
p.content, p.post_time
FROM post p
INNER JOIN user u
ON u.user_id = p.user_id
INNER JOIN
(
SELECT friend_id id
FROM friend
WHERE you = 1
UNION ALL
SELECT follows id
FROM follow
WHERE user_id = 1
) s ON p.user_id = s.ID
ORDER BY post_time DESC
LIMIT 10

Strange order of results when adding joins

I'm trying to build a commenting system on my website but having issues with ordering the comments correctly. This is a screenshot of what I had before it went wrong:
And this is the query before it went wrong:
SELECT
com.comment_id,
com.parent_id,
com.is_reply,
com.user_id,
com.comment,
com.posted,
usr.username
FROM
blog_comments AS com
LEFT JOIN
users AS usr ON com.user_id = usr.user_id
WHERE
com.article_id = :article_id AND com.moderated = 1 AND com.status = 1
ORDER BY
com.parent_id DESC;
I now want to include each comment's votes from my blog_comment_votes table, using a LEFT OUTER JOIN, and came up with this query, which works, but screws with the order of results:
SELECT
com.comment_id,
com.parent_id,
com.is_reply,
com.user_id,
com.comment,
com.posted,
usr.username,
IFNULL(c.cnt,0) votes
FROM
blog_comments AS com
LEFT JOIN
users AS usr ON com.user_id = usr.user_id
LEFT OUTER JOIN (
SELECT comment_id, COUNT(vote_id) as cnt
FROM blog_comment_votes
GROUP BY comment_id) c
ON com.comment_id = c.comment_id
WHERE
com.article_id = :article_id AND com.moderated = 1 AND com.status = 1
ORDER BY
com.parent_id DESC;
I now get this order, which is bizarre:
I tried adding a GROUP BY clause on com.comment_id but that failed too. I can't understand how adding a simple join can alter the order of results! Can anybody help back on the correct path?
EXAMPLE TABLE DATA AND EXPECTED RESULTS
These are my relevant tables with example data:
[users]
user_id | username
--------|-----------------
1 | PaparazzoKid
[blog_comments]
comment_id | parent_id | is_reply | article_id | user_id | comment
-----------|-----------|----------|------------|---------|---------------------------
1 | 1 | | 1 | 1 | First comment
2 | 2 | 1 | 1 | 20 | Reply to first comment
3 | 3 | | 1 | 391 | Second comment
[blog_comment_votes]
vote_id | comment_id | article_id | user_id
--------|------------|------------|--------------
1 | 2 | 1 | 233
2 | 2 | 1 | 122
So the order should be
First comment
Reply to first comment +2
Second Comment
It's difficult to say without looking at your query results, but my guess is that it's because you are only ordering by parent id and not saying how to order when two records have the same parent id. Try changing your query to look like this:
SELECT
com.comment_id,
com.parent_id,
com.is_reply,
com.user_id,
com.comment,
com.posted,
usr.username,
COUNT(c.votes) votes
FROM
blog_comments AS com
LEFT JOIN
users AS usr ON com.user_id = usr.user_id
LEFT JOIN
blog_comment_votes c ON com.comment_id = c.comment_id
WHERE
com.article_id = :article_id AND com.moderated = 1 AND com.status = 1
GROUP BY
com.comment_id,
com.parent_id,
com.is_reply,
com.user_id,
com.comment,
com.posted,
usr.username
ORDER BY
com.parent_id DESC, com.comment_id;

Get latest entry and join another table

I'm trying to get the username and timestamp of the most recent post where topicID is, for example, 88.
Users
id | username
--------|----------
45234 | kaka
32663 | lenny
52366 | bob
Posts
id | message | topicID | timestamp | userID
--------|-----------|---------|-----------|-------
675 | hello | 88 | 100 | 32663
676 | hey | 88 | 200 | 45234
677 | howdy | 88 | 300 | 52366
So here I would want postID 677 and user bob.
Can I do this in a single sql query?
Would be great if I could implent it into this:
SELECT topics.id, topics.subject, topics.forum_id
FROM topics WHERE topics.forumID = 16
Assuming that table Topic is linked with table Post by Topic.ID = Post.TopicID and you want to get the latest post associated with it, you can have a subquery which basically gets the latest id (assuming it's set as auto-incremented column) for each topicID and join the result on table Post to get the other columns. Also you need to join on table User in order to get the name of the user who posted the entry.
SELECT a.id,
a.subject,
a.forumid,
b.message,
b.timestamp,
d.username
FROM topic a
INNER JOIN Posts b
ON a.id = b.topicID
INNER JOIN
(
SELECT topicID, MAX(id) id
FROM Posts
GROUP BY topicID
) c ON b.topicID = c.topicID AND
b.id = c.ID
INNER JOIN users d
ON b.userID = d.id
WHERE a.forumID = 16
if you remove the WHERE clause, you will get all the latest entry for each forumID.
SQLFiddle Demo
Untested, but off the top of my head, I think the following query will get you what you want:
SELECT Users.username, Posts.timestamp
FROM Users JOIN Posts on Users.id = Posts.userID
WHERE Posts.topicID = 88
ORDER BY Posts.timestamp DESC
LIMIT 1

show results with biggest count mysql

I need to show user with the most comments. I have two tables:
Table: Users
ID | USERNAME | EMAIL
------------------------------
1 | USER01 | EMAIL01
2 | USER02 | EMAIL02
3 | USER03 | EMAIL03
4 | USER04 | EMAIL04
Table: Comments
ID | AUTHOR | COMMENT
----------------------------------
1 | USER01 | COMMENT...
2 | USER02 | COMMENT...
3 | USER01 | COMMENT...
4 | USER03 | COMMENT...
In this example the user01 have the most comments, but lets say I have to result them all with count of comments they have. And also in result I have to show users email which is stored in Users table.
How can I count and at same time check in both tables to return result? Or should I first get user info and then count ?
this query below handles duplicate rows having the most number of comments,
SELECT a.userName
FROM Users a
INNER JOIN Comments b
ON a.username = b.author
GROUP BY a.userName
HAVING COUNT(*) =
(
SELECT MAX(totalCount)
FROM
(
SELECT author, COUNT(*) totalCount
FROM comments
GROUP BY author
) a
)
SQLFiddle Demo
SQLFiddle Demo (with duplicate)
but if you want not to handle that, it can be simply done by using ORDER BY and LIMIT
SELECT a.userName, COUNT(*) totalCount
FROM Users a
INNER JOIN Comments b
ON a.username = b.author
GROUP BY a.userName
ORDER BY totalCount DESC
LIMIT 1
SQLFiddle Demo
select username,email,count(*) as cnt
from users, comments
where author = username
group by username
order by cnt desc
limit 1

mysql select a value within a select

I have an implementation messages system.
My problem is, I would like to know whether a user already has a thread with another user and if so what is the mid
I have a messages_recips table which look like this
---------------------------
| mid | seq | uid | status|
|--------------------------
| 4 | 1 | 1 | A |
| 4 | 1 | 2 | A |
---------------------------
if user id 1 having a thread with user id 2 I hold 2 rows with same mid.
I know I can create 2 sqls to achieve what I'm asking for, but I'm trying to do it in 1 sql.
As noted by Waqar Janjua, the key to this is a self-join query:
SELECT m1.mid
FROM messages_recips AS m1
JOIN messages_recips AS m2 ON m1.mid = m2.mid
WHERE m1.uid = 1
AND m2.uid = 2
I think you have to write a self-join query:
Select u.uid, u1.uid from tablename u
INNER JOIN tablename u1 on u.mid = u1.mid
You will get all the users who have the same mid.
In order to get only user1 and user2 records you have to place a where clause at the end of the query lik this.
Select u.uid, u1.uid from tablename u
INNER JOIN tablename u1 on u.mid = u1.mid
Where ( u.uid In ( 1,2 ) OR u1.uid In ( 1,2 ) ) ;