2012-06-09 5 views
1

사용자가 다른 사람에게 메시지를 보낼 수있는 메시징 시스템을 만들었습니다.mysql에서 메시지를 특정 형식으로 표시 PHP

두 개의 테이블을 만들었습니다.

메시지 표는 메시지와 관련된 모든 정보를 포함합니다 사용자가 처음으로 이야기하는 경우

conversation(conversation_id,user_id1,user_id2) 
    messages(message_id,conversation_id,sender_id,receiver_id,message,created_time) 

가하는 conversation_id이 (채팅을 시작) user_id1 및 user_id2 작성됩니다 (메시지를 보내는 user_id1 사람에).

이제 내가 원하는 것은 로그인 된 사용자가 created_time, group by conversation_id에 의해 다른 사용자의 모든 대화 목록을 볼 수있는 메시지 요약 페이지를 만드는 것입니다. (103)

conversation_id| conversation_with | last_message | created_time 
     3    102    MSG D   2012-06-08 08:41:10 
     2    101    MSG C   2012-06-08 08:40:20 
     1    100    MSG B   2012-06-08 08:39:40 

그래서이 출력은 다음과 같습니다

conversation_id | user_id1 | user_id2 
    1    100  103 
    2    101  103 
    3    103  102   


message_id| conversation_id| sender_id| receiver_id| message | created_time 
    1    1   100  103   MSG A 2012-06-08 08:38:57 
    2    1   103  100   MSG B 2012-06-08 08:39:40 
    3    2   101  103   MSG C 2012-06-08 08:40:20 
    4    3   102  103   MSG D 2012-06-08 08:41:10 

그리고 여기에 내가 무엇을 찾고 출력은 무엇인가 : 다음

테이블 데이터이다 ID로 로그인 한 사용자 말할 수있다 created_time에 의한 정렬, conversation_id에 의한 그룹화, conversation_with에있는 user의 id 표시, userid 103과 대화 중.

누군가가 MySQL 쿼리를 제공 할 수 있습니까?이 출력을 얻어야합니다.

답변

1

이것은 재미있었습니다. 따라서 해결해야 할 3 가지 주요 사항이 있습니다.

  1. 원하는 사용자가 두 열 사이에서 표시되는 위치에 따라 conversation_with 열을 바꾸십시오.
  2. greatest-n-per-group 가장 최근의 message을 찾으십시오.
  3. least-n-per-group 가장 빠른 메시지는 created_time입니다.

I에서, 열 user_id 교번 회 질의 결과 unioning하고 created_time하여 UNION을 결과를 주문에 의해 해결 첫번째. 나는 하나의 질의와 노조없이 이것을 해결할 수 있다고 생각하지만, 지금은 효과가있다.

2와 3은 조금 더 복잡합니다. 다음은 쿼리와 SQL 바이올린는 다음과 같습니다 http://sqlfiddle.com/#!2/bf2b7/1

TL; DNR

select * from (
    select c.conversation_id, c.user_id2 as conversation_with, m1.message as last_message, m3.created_time 
    from conversation as c 
     join messages as m1 on c.conversation_id = m1.conversation_id 
     left outer join messages as m2 on (c.conversation_id = m2.conversation_id 
             and (m1.created_time < m2.created_time OR m1.created_time = m2.created_time AND m1.message_id < m2.message_id)) 
     join messages as m3 on c.conversation_id = m3.conversation_id 
     left outer join messages as m4 on (c.conversation_id = m4.conversation_id 
             and (m3.created_time > m4.created_time OR m3.created_time = m4.created_time AND m3.message_id > m4.message_id)) 
    where user_id1 = 103 and m2.message_id is null and m4.message_id is null 
    union all 
    select c.conversation_id, c.user_id1 as conversation_with, m1.message as last_message, m3.created_time 
    from conversation as c 
     join messages as m1 on c.conversation_id = m1.conversation_id 
     left outer join messages as m2 on (c.conversation_id = m2.conversation_id 
             and (m1.created_time < m2.created_time OR m1.created_time = m2.created_time AND m1.message_id < m2.message_id)) 
     join messages as m3 on c.conversation_id = m3.conversation_id 
     left outer join messages as m4 on (c.conversation_id = m4.conversation_id 
             and (m3.created_time > m4.created_time OR m3.created_time = m4.created_time AND m3.message_id > m4.message_id)) 
    where user_id2 = 103 and m2.message_id is null and m4.message_id is null 
             ) as conversations 
order by created_time desc 
+0

좋아! 당신은 그것을했다! 속도와 성능을 고려한다면 어떨까요? – Jadzia

+0

많은 성능 테스트를 수행해야하지만 일반적으로 '그룹당 최대/최소 그룹당'이 매우 효율적입니다. 'created_time'에 추가하고 색인을 붙이고, 메시지와 대화 사이에 외래 키를 만들면 색인이 생성됩니다. – HackedByChinese

+0

일부 기본 키, 인덱스 및 외래 키가있는 버전으로 SQL 바이올린을 업데이트했습니다. – HackedByChinese

관련 문제