Join table with order by and group by - mysql

SELECT * FROM(
SELECT c_id, user_id, message, state, time FROM message
WHERE receive=1
ORDER BY message_id DESC
)AS t GROUP BY c_id
I have mysql statement can fetch out last message for user.
however i need to join the user table, so i can fetch out the sender's name
LEFT JOIN user ON user.user_id=message.user_id
How to achieve this?
//user
user_id name
//conversation
c_id user_id
//message
m_id c_id user_id(sender) receive message state time

SELECT * FROM (
SELECT c_id, user_id, message, state, time
FROM message
WHERE receive=1
ORDER BY message_id DESC) AS t
LEFT JOIN user ON user.user_id=t.user_id
GROUP BY c_id
P.S. check if user.user_id exists.

Related

Get the last message from each conversation

I have table for messages which contains id, sender_id, receiver_id, message and conversation_id
(I connected them by conversation_id, which they make by sending first message and if someone is replying, first he search conversation_id from messages where he is receiver and guy where is he replying is sender and by that send message with same conversation_id)
Now in messages list I want to output one just one last row per different conversation_id where sender_id='$my_id' OR receiver_id='$my_id'
I am using DISTINCT but I get all rows always as output:
SELECT DISTINCT conversation_id, sender_id, message
FROM messages
WHERE receiver_id='$my_id'
ORDER BY id DESC
try this
SELECT id,conversation_id, sender_id, receiver_id, message FROM message WHERE receiver_id='$my_id' GROUP BY `conversation_id` ORDER BY id DESC LIMIT 1
Please give the following query a try:
SELECT
M.*
FROM messages M
INNER JOIN
(
SELECT
MAX(id) AS last_id_of_conversation,
conversation_id
FROM messages
GROUP BY conversation_id
) AS t
ON M.id = last_id_of_conversation
Explanation:
SELECT
MAX(id) AS last_id_of_conversation,
conversation_id
FROM messages
GROUP BY conversation_id;
This inner query will generate an output where there will be one row for each conversation_id along with the last id value (or max id) of the conversation.
Later make an inner join between your main table (messages) and the result returned by the inner query on matching id. I hope id is primary key. If so, then the above query ensures to bring a single row (more specifically the row having the last message) for each conversation.
EDIT:
SELECT
M.*
FROM messages M
INNER JOIN
(
SELECT
MAX(id) AS last_id_of_conversation,
conversation_id
FROM messages
WHERE sender_id = ? OR receiver_id = ?
GROUP BY conversation_id
) AS t
ON M.id = last_id_of_conversation

How do I select a row with max count doing a group by

I have a table posts with columns (id, user_name, thread_id).
A user can submit multiple posts for a thread. thread to post is one to many.
I need to find out who submitted max posts per thread. So the result would be
Max(Count), user_name, thread_id WHERE there will be only one row per thread_id.
The table is too huge so I wanted to get the query optimized as much as I could.
You can try with the group by and having clauses:
select t.user_name, t.thread_id , count(*) as max_count
from tbl t
group by t.user_name, t.thread_id
having count(*) = ( select count(*) as ttl
from tbl
where thread_id = t.thread_id
group by user_name
order by ttl desc
limit 1 )
select user_name, thread_id, count(*) as max
from tbl t
group by user_name, thread_id
having count(*) = (
select count(*) as cnt /* most posts per user per thread */
from tbl
group by user_name, thread_id
order by cnt desc
limit 1
)
Easy workaround for system that don't have limit is:
select user_name, thread_id, count(*) as max
from tbl t
group by user_name, thread_id
having count(*) = (
select max(cnt) from (
select count(*) as cnt /* most posts per user per thread */
from tbl
group by user_name, thread_id
) m
)
Suppose you have a table posts with fields id, user_name & thread_id.
If you want to query which user has posted the most posts on a specific thread and the total number of his posts from a table, you can achieve that with this MySQL query:
SELECT user_name, thread_id, count(thread_id)
FROM posts WHERE thread_id=1 GROUP BY user_name
ORDER BY count(thread_id) DESC LIMIT 1;
It will return only one row...

how to get a list of users I have interacted with in a messaging system

I am trying to get a list of users that I have interacted with in a messaging system:
TABLE:
messages: id, sender_id, recipient_id, message, date
SQL:
SELECT * FROM `messages`
WHERE
(`sender_id` = :user_id OR `recipient_id` = :user_id)
GROUP BY `sender_id`, `recipient_id`
ORDER by `date` DESC
This gives me multiple rows with mismatched sender / recipient id's
I think its the GROUP BY thats causing it by not sure how to fix it
EDIT: I only need 1 row per interaction ( hence the GROUP BY )
GROUP BY will combine all the rows with the same sender_id and recipient_id. Use a UNION to combine the two groups into one set of results:
SELECT correspondent, MAX(date) AS last_date
FROM (
SELECT sender_id as correspondent, date
FROM messages
WHERE recipient_id = :user_id
UNION ALL
SELECT recipient_id as correspondent, date
FROM messages
WHERE send_id = :user_id) x
GROUP BY correspondent
ORDER BY last_date DESC

what should be the mysql query to fetch recently added message by a group of users which are stored in the same table

I have the following table structure
and i want the result to be
Here is the query which i tried
select * from table where userid IN(201,202,203,204,205)
group by userid
order by messageid desc
But i dint get the latest records based on messageid.
I need to write this in a single query as i must use order by clause
Please explain my mistake and provide a solution
You can join the table to itself using the max of the messageid if I'm understanding your question correctly:
select t.messageid, t.userid, t.data
from yourtable t
join (
select max(messageid) maxmessageid, userid
from yourtable
where userid in (201,202,203,204,205)
group by userid
) t2 on t.userid = t2.userid and t.messageid = t2.maxmessageid
order by t.messageid desc
SQL Fiddle Demo
Edit: Here's an alternative approach using IN:
select messageid, userid, data
from yourtable
where messageid in (
select max(messageid) maxmessageid
from yourtable
where userid in (201,202,203,204,205)
group by userid
)
order by messageid desc
More Fiddle
SELECT yourtable.*
FROM
yourtable INNER JOIN (SELECT userid, MAX(messageid) max_messageid
FROM yourtable
WHERE userid IN (201,202,203,204,205)
GROUP BY userid) mx
ON yourtable.messageid=mx.max_messageid
AND yourtable.userid=mx.userid

Selecting newest distinct email address from table

Very quick one:
I've done this before, but having a bit of a mind blank right now.
SELECT max(id) as id, username, email
FROM user_info
WHERE username!=''
GROUP by id,email
Unfortunately this is not working. It will select the max id but not then the corresponding data from that row.
If you have multiple ids per email address, then you can use max(id) and group by the email only.
SELECT max(id) as id, username, email
FROM user_info
WHERE username <> ''
GROUP by email, username
You can use a subquery which will return the max id in the subquery and then you use that to self join on the table to return the most recent id, username and email:
SELECT u.id, u.username, u.email
FROM user_info u
INNER JOIN
(
select max(id) maxid, email
from user_info
where username <> ''
group by email
) u2
on u.id = u2.maxid
See SQL Fiddle with Demo
Select DISTINCT(email), MAX(id)
FROM user_info
GROUP by email
ORDER BY id DESC