Frage

I'm not very experienced with data bases (only do certain amount of work acceptable for the front-end developer)

Anyway, I ran into the problem, that I am trying to solve in MySQL... Let's say I have two related tables tables:

users (id INT, user_name VARCHAR(20))

id  name
-----------------
1   Mike
2   Maria
3   John

message (id INT, user_id INT, message TEXT, created DATE)

id    user_id    message        created
--------------------------------------------------
1     1          message 1      2014-05-01 12:12
2     3          message 2      2014-05-01 15:27
3     2          message 3      2014-05-02 14:57
4     2          message 4      2014-05-02 16:14
5     3          message 5      2014-05-03 16:15
6     1          message 6      2014-05-07 10:39
7     1          message 7      2014-05-01 12:27
8     1          message 8      2014-05-02 20:16
9     2          message 9      2014-05-03 05:01
10    1          message 10     2014-05-04 11:05
11    2          message 11     2014-05-06 20:41
12    1          message 12     2014-05-07 14:32
13    3          message 13     2014-05-08 12:54
14    3          message 14     2014-05-09 23:20
15    1          message 15     2014-05-11 00:45

I need to come out following output to display last 3 messages for each user:

id   name        m1             m2            m3
------------------------------------------------------------
1    Mike        message 15     message 12    message 6
2    Maria       message 11     message 9     message 4
3    John        message 14     message 13    message 5

Intuitively I understand that I have to use Inner Join, but my brain starts to melt after second or third line.

There've been number of examples where the output was only for the last message (m1), but they were using sort to find the last message.

Any help would be appreciated.

Update:

I was initially trying to do it with a left join, but then end up with this one. I mean it worked (but really badly). It was concatting all the messages into one string line (1024 chars).

 SELECT u.name, GROUP_CONCAT(message ORDER BY message.created DESC) messages
 FROM messages m, users u
 WHERE u.id = m.user_id
War es hilfreich?

Lösung

If you were using a different RDBMS, this wouldn't be as difficult. But basically you need to get a row number per user, and then take the most recent using max with case.

Something like this should work:

select u.id,
  u.user_name, 
  max(case when rn=1 then message end) m1,
  max(case when rn=2 then message end) m2,
  max(case when rn=3 then message end) m3
from users u
  join (
      select id, 
        user_id,
        message,
        @rn:=IF(user_id=@prevUserId,@rn+1,1) rn,
        @prevUserId:=user_id,
        created
      from message 
        join (select @prevUserId:= 0, @rn:= 0) t
      order by user_id, created desc  
    ) m on u.id = m.user_id
group by u.id, u.user_name
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top