3

I want to sort the last messages with every user that a specific user has chated from ejabberd archive table.

The fields that I'm using are these

  • id (message id)
  • username (username copy)
  • bare_peer (user that is chatting with)
  • txt (text chat)
  • created_at (time created)

What I'm trying to achieve is something like that, but I need to group message by bare_peer with username as 1_usernode, but only the last messages.

I already tested a lot of queries, but none of them worked. This is the first query I tried.

SELECT id, username, bare_peer, txt FROM archive where
username = '1_usernode' GROUP BY bare_peer ORDER BY created_at DESC;

And this is the output.

+------+------------+-------------------------------------------------------+---------------------+
| id   | username   | bare_peer              | txt                          | created_at          |
+------+------------+------------------------+------------------------------+---------------------+
| 1095 | 1_usernode | 10_usernode@localhost  | Hello !!!                    | 2016-07-17 21:15:17 |
| 1034 | 1_usernode | 15_usernode@localhost  | hey sup ?                    | 2016-07-13 22:40:29 |
| 1107 | 1_usernode | 13_usernode@localhost  | oi                           | 2016-07-18 00:09:28 |
| 1078 | 1_usernode | 2_usernode@localhost   | Hello this is just a Test!!! | 2016-07-15 16:30:50 |
| 1101 | 1_usernode | 7_usernode@localhost   | hey                          | 2016-07-18 00:05:55 |
| 1084 | 1_usernode | 3_usernode@localhost   | Hey how are you?             | 2016-07-15 19:36:44 |
| 1085 | 1_usernode | 4_usernode@localhost   | Hey how are you doing ?      | 2016-07-17 19:20:00 |
double-beep
  • 5,031
  • 17
  • 33
  • 41
RenatoCv
  • 31
  • 5
  • Is your created_at column set as the datetime datatype? – Leopold Stotch Sep 27 '16 at 12:49
  • Since all of the `bare_peer` in your sample output are unique, it seems to have followed your query correctly. Did you mean to group by `username`? – Sablefoste Sep 27 '16 at 12:49
  • It would help if you showed the input data & your expected output. Maybe create an sql fiddle – PaulF Sep 27 '16 at 12:55
  • The output is correct but it gives me the oldest messages what i need is the newest. – RenatoCv Sep 27 '16 at 12:55
  • Your goal cannot be achieved using `GROUP BY` because `GROUP BY` does something else. It does not return rows from the database, it generates new rows using the data it extracts from the database. The query you posted is not valid SQL. Two (or more) different rows having the same value for `bare_peer` land in the same group. They have different values for `id` but you want to `SELECT id`. What `id`? – axiac Sep 27 '16 at 13:00
  • created_at is set as timestamp (current_timestamp) – RenatoCv Sep 27 '16 at 13:00
  • Take a look at [this answer](http://stackoverflow.com/a/28090544/4265352). It solves the same problem. – axiac Sep 27 '16 at 13:12

7 Answers7

0

Try this query :-

SELECT archive.id, archive.max_id, archive.username, archive.bare_peer, archive.txt 
FROM archive join 
(SELECT MAX(id) max_id, username, bare_peer, txt 
FROM archivewhere username = '1_usernode' GROUP BY bare_peer)
tab on archive.id=tab.max_id
Abhishek Sharma
  • 6,689
  • 1
  • 14
  • 20
  • 1
    It returns me the oldest messages but thanks anyway! – RenatoCv Sep 27 '16 at 12:58
  • SELECT * FROM archive join (SELECT MAX(id) max_id, username, bare_peer, txt FROM archive where username = '1_usernode' GROUP BY bare_peer) tab on archive.id=tab.max_id try this query @RenatoCv – Abhishek Sharma Sep 27 '16 at 13:03
  • `SELECT *` and `GROUP BY` in the same query is not valid SQL. – axiac Sep 27 '16 at 13:05
  • 1
    the output returns me the time and id of the newest message that is correct combined with the text content of the older. it's almost working. – RenatoCv Sep 27 '16 at 13:12
  • SELECT archive.id, archive.max_id, archive.username, archive.bare_peer, archive.txt FROM archive join (SELECT MAX(id) max_id, username, bare_peer, txt FROM archivewhere username = '1_usernode' GROUP BY bare_peer) tab on archive.id=tab.max_id try this query @RenatoCv – Abhishek Sharma Sep 27 '16 at 13:22
0

Use This Query It's Helful.

SELECT MAX(id), username, bare_peer, txt FROM archive where
username = '1_usernode' ORDER BY created_at DESC
  • Because of the implicit grouping (an aggregate function is used but no `GROUP BY` clause is present), this query returns a single row, rendering the `ORDER BY` clause useless (the query doesn't return the expected result, anyway). – axiac Sep 27 '16 at 13:04
0

declare created_at as datetime

try this

DROP TABLE IF EXISTS `archive`;

CREATE TABLE `archive` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `username` VARCHAR(50) DEFAULT NULL,
  `bare_peer` VARCHAR(50) DEFAULT NULL,
  `txt` TEXT,
  `created_at` DATETIME DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=INNODB  DEFAULT CHARSET=latin1;

/*Data for the table archive */

INSERT  INTO `archive`(`id`,`username`,`bare_peer`,`txt`,`created_at`) 
VALUES (1034,'1_usernode','15_usernode@localhost','hey sup ?','2016-07-13 22:40:29'),
(1078,'1_usernode','2_usernode@localhost','Hello this IS just a Test!!!','2016-07-15 16:30:50'),
(1084,'1_usernode','3_usernode@localhost','Hey how are you?','2016-07-15 19:36:44'),
(1085,'1_usernode','4_usernode@localhost','Hey how are you doing ?','2016-07-17 19:20:00'),
(1095,'1_usernode','10_usernode@localhost','Hello !!!','2016-07-17 21:15:17'),
(1101,'1_usernode','7_usernode@localhost','hey','2016-07-18 00:05:55'),
(1107,'1_usernode','13_usernode@localhost','oi','2016-07-18 00:09:28');

Then run your query

SELECT id, username, bare_peer, txt FROM archive where
username = '1_usernode' GROUP BY bare_peer ORDER BY created_at DESC;
Rafiqul Islam
  • 1,636
  • 1
  • 12
  • 25
  • If i just modify the column in question, should it work anyway? – RenatoCv Sep 27 '16 at 13:17
  • I created a second table called archive2 with your data and added more data with a earlier date. but it returns me always the oldest messages. – RenatoCv Sep 27 '16 at 13:29
0

Try this following code:-

select m.*
from
messages m
inner join (
select max(id) as maxid
from messages
group By (if(username > bare_peer,  username, bare_peer)), 
(if(username > bare_peer,  bare_peer, username))
) t1 on m.id=t1.maxid ;

m is alias of message table

kunal
  • 4,122
  • 12
  • 40
  • 75
0

You want the entry with max(created_at) for every username and bare_peer. One way to do that in MySQL is with 'having' but I don't like that. I would first get the max(created_at) for every entry:

select username, bare_peer, max(created_at) as m_
from archive
group by username, bare_peer;

Then join the table on that result:

select b.*
from (
    select username, bare_peer, max(created_at) as m_
    from archive
    group by username, bare_peer
) a
inner join archive as b on (
    a.username = b.username
    and a.bare_peer = b.bare_peer
    and a.m_ = b.created_at
)
verhie
  • 1,298
  • 1
  • 7
  • 7
0

I want to know why it shows the created_at column when you don't select created_at? And I don't know why you use group by? There is nothing need to be divided into groups.

My statement looks like this.select id, username, bare_peer, txt, created_at from archive where username = '1_usercode' order by created_at desc

A.Flash
  • 71
  • 1
0

I created a temporary solution with the Rahauto's answer. I put his query that returns me the correct id from latest message inside a subquery so that i can extract message content from it's id.

SELECT username, bare_peer, txt, created_at FROM archive WHERE id IN (
  SELECT tab.max_id  FROM
    archive JOIN (SELECT MAX(id) max_id, username, bare_peer, txt FROM
    archive WHERE username = '1_usernode' GROUP BY bare_peer)
  tab ON archive.id=tab.max_id
);
RenatoCv
  • 31
  • 5