I have the following table to represent a conversation between users.
message | user1 | user2 | unixtime
msg1 | 14 | 21 | -
msg2 | 21 | 12 | -
msg1 | 14 | 18 | -
msg3 | 14 | 21 | -
msg2 | 18 | 14 | -
msg4 | 21 | 12 | -
I want to show a list of a a specific user's conversations by selecting all messages with current_user = user1 or user2.
So far this SELECT will select the correct messages but the grouping doesn't work correctly.
SELECT * FROM (
SELECT * FROM messages
WHERE user1 = '".$_SESSION['login']['ID']."'
OR user2 = '".$_SESSION['login']['ID']."'
ORDER BY unixtime DESC
) as list
GROUP BY user1, user2
ORDER BY unixtime DESC
It will only group the messages with the same user1 and user2 and not if the two users are reversed.
Is this done by a more advanced grouping or should I join the table in some way?
It is unclear what you want the query to do, because you are using group by and select *. The select * returns indeterminate values from matching rows. I don't know why anyone would want to do this. You can read about this in the documentation.
If you want to counts the messages:
SELECT least(user1, user2), greatest(user1, user2), count(*)
FROM messages
WHERE '".$_SESSION['login']['ID']."' in (user1, user2)
GROUP BY least(user1, user2), greatest(user1, user2)
Related
I need to develop chat application in php for this i have created two tables likes users and message. every user details will be stored in users table and every message will be stored in messages table.I have done storing part it is working fine. Now i need to display messages.So as per my requirement.
when any user logs into his portal he/she will be able to see latest messaged users list.And if he want to message any of other users ,he just clicks on there profile pic than a message panel will be opened .Untill here i completed everything.
But my issue is i need to display
latest messaged users list,
in this i need to show user first name, profile picture,last message, last message date.
And one more condition is i need to display the list like latest messaged user first.
I have tried in many ways but i got users list with first message i don't want like that i need last message for that user
My tables are
Users table
uid | firstname | email | mobile
---------------------------------------------
1 | kumar | kumar#gmail.com | 9876543210
----------------------------------------------
2 | jack | jack#gmail.com | 8876543216
----------------------------------------------
3 | rams | rams#gmail.com | 7876543215
----------------------------------------------
4 | devid | devid#gmail.com | 9876543220
----------------------------------------------
5 | joe | joe#gmail.com | 8876543212
----------------------------------------------
messages table
mid| from_id | to_id | message | created_at
----------------------------------------------------------------
1 | 1 | 2 | hello jack | 2017-02-03 09:00:52
----------------------------------------------------------------
2 | 2 | 1 | hi kumar | 2017-02-03 09:10:30
----------------------------------------------------------------
3 | 2 | 3 | ram where are you | 2017-02-03 09:15:02
----------------------------------------------------------------
4 | 3 | 2 | at home | 2017-02-03 09:35:20
----------------------------------------------------------------
5 | 1 | 2 | hello how are you | 2017-02-03 09:42:55
----------------------------------------------------------------
6 | 4 | 2 | good morning | 2017-02-03 09:50:45
----------------------------------------------------------------
8 | 1 | 3 | hi | 2017-02-03 09:54:22
----------------------------------------------------------------
7 | 3 | 1 | hello kumar | 2017-02-03 09:58:38
----------------------------------------------------------------
For example i have logged in as kumar(uid=1)
Expected output:
firstname | message | mid | uid
-----------------------------------------
rams | hello kumar | 7 | 3
-----------------------------------------
jack | hello how are you | 5 | 2
-----------------------------------------
I have tried like this :
SELECT DISTINCT
`u`.`firstname`,
`u`.`profile_photo`,
`u`.`uid`,
`u2`.`firstname`,
`u2`.`profile_photo`,
`u2`.`uid`,
`message`,
`messages`.`created_at`,
`messages`.`from_id`,
`messages`.`to_id`,
`messages`.`mid`
FROM
`messages`
INNER JOIN
`users` AS `u` ON `u`.`uid` = `messages`.`from_id`
INNER JOIN
`users` AS `u2` ON `u2`.`uid` = `messages`.`to_id`
WHERE
(from_id = 1 OR to_id = 1)
GROUP BY
`u`.`uid`,
`u2`.`uid`
ORDER BY
`messages`.`mid` DESC
But got output like this
firstname | message | mid | uid
-----------------------------------------
jack | hello jack | 1 | 2
-----------------------------------------
rams | hi | 5 | 2
-----------------------------------------
Thanks in advance
try this way
SELECT DISTINCT `u`.`firstname`,`u`.`profile_photo`, `u`.`uid`, `u2`.`firstname`,`u2`.`profile_photo`,`u2`.`uid`, `message`,`messages`.`created_at`, `messages`.`from_id`,`messages`.`to_id`,`messages`.`mid`
FROM `messages`
INNER JOIN `users` AS `u` ON `u`.`uid` = `messages`.`from_id`
INNER JOIN `users` AS `u2` ON `u2`.`uid` = `messages`.`to_id`
WHERE (from_id = 1 OR to_id = 1)
GROUP BY `u`.`uid`, `u2`.`uid`
ORDER BY `messages`.`created_at` DESC
It appears that you want to put messages in the same group if they're between the same two users, regardless of the direction. To do this, change your GROUP BY to:
GROUP BY GREATEST(u.uid, u2.uid), LEAST(u.uid, u2.uid)
Use this along with the solutions in SQL Select only rows with Max Value on a Column to get the first or last message in each conversation found using this grouping.
You should also give aliases to the columns from u and u2 in the SELECT clause, so you can distinguish the sender and receiver information in the result.
SELECT u.firstname AS sender_name, u.profile_photo AS sender_photo, ...
Or since one of the users is always kumar, you could just select only the information about the other user:
SELECT IF(from_id = 1, u2.firstname, u1.firstname) AS firstname,
IF(from_id = 1, u2.profile_photo, u1.profile_photo) AS profile_photo,
...
I have a table that keeps record of vote
Condition
Reply can have many votes;
User can vote once to specific reply id.
table: reply_vote
+----+-------------+-------------+
| id | reply_id | userID |
+----+-------------+----+--------+
| 1 | 23 | 21 |
| 3 | 33 | 21 |
| 4 | 23 | 25 |
| 5 | 23 | 12 |
I want to display the total votes on each reply
e.g
reply_id 23 has 3 votes with userid (21,25,12)
reply_id 33 has 1 vote with userid (21)
I don't want to fetch all data using while loop in php
up till now I have used below query but it is displaying all the votes on the page which is not what is required
SELECT
reply.id,
reply.reply,
COUNT(reply_vote.id) AS likes
FROM reply
LEFT JOIN reply_vote ON reply_vote.reply_id = reply.id
GROUP BY reply.id
How can I do that?
Try this code:
SELECT reply.id, reply.reply,
COUNT(reply_vote.id) as likes
FROM reply
INNER JOIN reply_vote ON reply_vote.reply_id = reply.id
GROUP BY reply_vote.reply_id
I am trying to built the messaging system and I want to select distinct value from the table and sort by date and also return the read and unread status. My table structure is as id, from_user_id, to_user_id, message, datetime, read . Suppose dummy data are as follows:
id | from_user_id | to_user_id | message | datetime | read
1 | 20 | 50 | hi | 2016-3-13 06:05:30 | 1
2 | 20 | 50 | hey | 2016-3-13 06:15:30 | 0
3 | 30 | 50 | hi | 2016-3-14 06:05:30 | 0
Now I want to select distinct from_user_id and sort by date so that I can display the name of the user who is chating recently on top of list and also return the read status 1, if any of the rows with from_user_id has read status 0, then I want to return read as 0 so that I can differentiate whose user message has unread message.
Suppose, from_user_id has read status as 0 in one rows then I want to return read status as 0 when returning distinct value of from_user_id. How can I do it. I tried as follows but won't work in my case. It returns distinct value but not sorted by date and also read status in not returning what I expect.
select distinct(`from_user_id`),register.name FROM message INNER JOIN register ON register.id = message.from_user_id where message.to_user_id = $user_id GROUP BY message.id ORDER BY MAX(datetime) ASC
Try the following query:
SELECT
message.from_user_id,
register.name,
message.read
FROM message
INNER JOIN
(
SELECT
from_user_id,
MAX(datetime) max_datetime
FROM message
WHERE to_user_id = 50
GROUP BY from_user_id ) t
ON t.from_user_id = message.from_user_id AND t.max_datetime = message.datetime
INNER JOIN register ON register.id = message.from_user_id
WHERE message.to_user_id = 50
ORDER BY message.datetime ASC
UPDATED SQL FIDDLE
Sample Input:
id | from_user_id | to_user_id | message | datetime | read
1 | 20 | 50 | hi | 2016-3-13 06:05:30 | 1
2 | 20 | 50 | hey | 2016-3-13 06:15:30 | 0
3 | 30 | 50 | hi | 2016-3-14 06:05:30 | 0
Output:
from_user_id name read
20 User20 0
30 User30 0
Note: This query might give you multiple row for the same from_user_id if there exists multiple entries in your message table having the same datetime and same to_user_id.
checkout this query :
SELECT DISTINCT(form_user_id),MIN(read) FROM table_name ORDER BY datetime ASC
I've a following query to select data from a table (chat) in a chat system:
SELECT * FROM (SELECT * FROM chat WHERE id_chat = '$chat_id' ORDER BY id DESC LIMIT 10) S
WHERE id_chat = '$chat_id'
ORDER BY id ASC
LIMIT 10
In this table (chat), there is a user column where it is the user id that sent the message.
I would, from the id_from of the user who sent the message, get back data that user (users table).
Table chat:
id | id_chat | id_from | id_to | message | date
1 | 23 | 1 | 2 | hello! | 01-12-2016
Table users:
id | name | photo
1 | John | pic.png
2 | Nick | hey.jpg
What better way to do it using the above query? LEFT JOIN? INNER JOIN? And, how do?
The following is a simplified version of the problem I'm trying to solve. I just can't figure it out.
I have two tables:
Table 1: messages
id | timestamp | message
------------------------
1 | 2014-01-20 09:00:00 | Hello I'm a message
2 | 2014-01-20 09:00:00 | Second message for you
3 | 2014-01-27 11:00:00 | This message has been updated
4 | 2014-01-28 13:45:00 | Last message for now
and
Table 2: reads
id | message_id | user_id | last_read_timestamp
------------------------
1 | 1 | 1 | 2014-01-20 09:10:00
1 | 2 | 1 | 2014-01-20 09:15:00
1 | 3 | 1 | 2014-01-24 19:25:00
1 | 1 | 2 | 2014-01-28 13:45:00
id in Table a relates to message_id in Table 2.
The messages in Table A are updated frequently and the timestamp is updated. So I need to run a query that will return the Table A id of any messages that have been updated SINCE they were read for a particular user_id, for that the user hasn't read (and therefore no corresponding entry appears in Table 2.
So for user_id = 1, message_id 3 has been updated since being read, and message_id 4 is a new message. The result for user_id = 1 would be:
Unread
------
3
4
I've tried a LEFT JOIN between the tables but just can't seem to get the correct result.
If you just need to retrieve messages unread for a single user, you could use something like this:
SELECT messages.id AS unread
FROM
messages LEFT JOIN (SELECT message_id, MAX(last_read_timestamp) as last_rd
FROM reads
WHERE user_id = 1
GROUP BY message_id) lr
ON messages.id = lr.message_id
AND messages.timestamp < lr.last_rd
WHERE
lr.message_id IS NULL
The Table A id of any messages that have been updated SINCE they were read for a particular user_id; will give below query.(not tested)
select * from table1
left join table2 on (table1.id=table2.message_id && table1.timestamp>table2.last_read_timestamp)
where table2.user_id=1;