Search code examples
mysqligroup-concat

Create a GROUP BY query to show the latest row


So my tables are:
user_msgs: http://sqlfiddle.com/#!9/7d6a9
token_msgs: http://sqlfiddle.com/#!9/3ac0f

There are only these 4 users as listed. When a user sends a message to another user, the query checks if there is a communication between those 2 users already started by checking the token_msgs table's from_id and to_id and if no token exists, create token and use that in the user_msgs table. So the token is a unique field in these 2 tables.

Now, I want to list the users with whom user1 has started the conversation. So if from_id or to_id include 1 those conversation should be listed.

There are multiple rows for conversations in the user_msgs table for same users.

I think I need to use group_concat but not sure. I am trying to build the query to do the same and show the latest of the conversation on the top, hence ORDER BY time DESC:

SELECT * FROM (SELECT * FROM user_msgs ORDER BY time DESC) as temp_messages GROUP BY token 

Please help in building the query.

enter image description here

Thanks.

CREATE TABLE `token_msgs` (
  `id` int(11) NOT NULL,
  `from_id` int(100) NOT NULL,
  `to_id` int(100) NOT NULL,
  `token` varchar(50) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

--
-- Dumping data for table `token_msgs`
--

INSERT INTO `token_msgs` (`id`, `from_id`, `to_id`, `token`) VALUES
(1, 1, 2, '1omcda84om2'),
(2, 1, 3, '1omd0666om3'),
(3, 4, 1, '4om6713bom1'),
(4, 3, 4, '3om0e1abom4');


---


CREATE TABLE `user_msgs` (
  `id` int(11) NOT NULL,
  `token` varchar(50) NOT NULL,
  `from_id` int(50) NOT NULL,
  `to_id` int(50) NOT NULL,
  `message` text NOT NULL,
  `time` datetime NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

--
-- Dumping data for table `user_msgs`
--

INSERT INTO `user_msgs` (`id`, `token`, `from_id`, `to_id`, `message`, `time`) VALUES
(1, '1omcda84om2', 1, 2, '1 => 2\r\nCan I have your picture so I can show Santa what I want for Christmas?', '2016-08-14 22:50:34'),
(2, '1omcda84om2', 2, 1, 'Makeup tip: You\'re not in the circus.\r\n2=>1', '2016-08-14 22:51:26'),
(3, '1omd0666om3', 1, 3, 'Behind every fat woman there is a beautiful woman. No seriously, your in the way. 1=>3', '2016-08-14 22:52:08'),
(4, '1omd0666om3', 3, 1, 'Me: Siri, why am I alone? Siri: *opens front facing camera*', '2016-08-14 22:53:24'),
(5, '1omcda84om2', 1, 2, 'I know milk does a body good, but damn girl, how much have you been drinking? 1 => 2', '2016-08-14 22:54:36'),
(6, '4om6713bom1', 4, 1, 'Hi, Im interested in your profile. Please send your contact number and I will call you.', '2016-08-15 00:18:11'),
(7, '3om0e1abom4', 3, 4, 'Girl you\'re like a car accident, cause I just can\'t look away. 3=>4', '2016-08-15 00:42:57'),
(8, '3om0e1abom4', 3, 4, 'Hola!! \r\n3=>4', '2016-08-15 00:43:34'),
(9, '1omd0666om3', 3, 1, 'Sometext from 3=>1', '2016-08-15 13:53:54'),
(10, '3om0e1abom4', 3, 4, 'More from 3->4', '2016-08-15 13:54:46');

Solution

  • Let's try this (on fiddle):

    SELECT * 
    FROM (SELECT * FROM user_msgs
      WHERE from_id = 1 OR to_id = 1
      ORDER BY id DESC
    ) main
    GROUP BY from_id + to_id
    ORDER BY id DESC
    

    Thing to mention GROUP BY from_id + to_id this is because sum makes it unique for each conversation between two persons: like from 1 to 3 is same as from 3 to 1. No need for extra table, and it makes it harder to maintain

    UPDATE:

    Because sometimes GROUPing works weird in MySQL I've created new approach to this problem:

    SELECT 
      a.* 
    FROM user_msgs a 
    LEFT JOIN user_msgs b 
        ON ((b.`from_id` = a.`from_id` AND b.`to_id` = a.`to_id`) 
          OR (b.`from_id` = a.`to_id` AND b.`to_id` = a.`from_id`)) 
        AND a.`id` < b.`id` 
    WHERE (a.from_id = 1 OR a.to_id = 1) 
      AND b.`id` IS NULL 
    ORDER BY a.id DESC