2014-10-16 30 views
0

我正在創建一個小的消息平臺,我有三個表:MySQL查詢以笛卡爾積

`msg_conversations` 
+-------+---------------------+------+-----+---------+----------------+ 
| Field | Type    | Null | Key | Default | Extra   | 
+-------+---------------------+------+-----+---------+----------------+ 
| id | int(10) unsigned | NO | PRI | NULL | auto_increment | 
+-------+---------------------+------+-----+---------+----------------+ 

`msg_participants` 
+------------+---------------------+------+-----+---------+----------------+ 
| Field  | Type    | Null | Key | Default | Extra   | 
+------------+---------------------+------+-----+---------+----------------+ 
| id   | int(10) unsigned | NO | PRI | NULL | auto_increment | 
| convo_id | int(10) unsigned | NO | MUL | NULL |    | 
| prof_id | int(10) unsigned | NO | MUL | NULL |    | 
| prof_type | tinyint(3) unsigned | NO |  | NULL |    | 
| is_visible | tinyint(3) unsigned | NO |  | NULL |    | 
+------------+---------------------+------+-----+---------+----------------+ 

`msg_messages` 
+----------------+---------------------+------+-----+---------+----------------+ 
| Field   | Type    | Null | Key | Default | Extra   | 
+----------------+---------------------+------+-----+---------+----------------+ 
| id    | int(10) unsigned | NO | PRI | NULL | auto_increment | 
| participant_id | int(10) unsigned | NO | MUL | NULL |    | 
| message  | text    | NO |  | NULL |    | 
| time_cre  | int(11)    | NO |  | NULL |    | 
+----------------+---------------------+------+-----+---------+----------------+ 

我想與convo_id的每個沿回的最新消息,(通過msg_messages.time_cre)我的邏輯如下:1)獲取用戶參與的所有對話ID(由msg_participants.prof_type和msg_participants.prof_id定義)。 2)根據每個對話ID獲取每個參與者。 3)返回每個對話中的最後一條消息(按msg_messages.time_cre排序)。該功能應與Facebook返回對話列表以及每次對話中最後一條消息的預覽類似。

這裏是我到目前爲止的代碼:

SELECT msg_participants.convo_id, 
    msg_messages.id, 
    msg_participants.prof_id, 
    msg_participants.prof_type, 
    SUBSTRING(msg_messages.message,1,50) as message, 
    msg_messages.time_cre 
FROM msg_participants,msg_messages 
WHERE 
    msg_participants.id IN 
     (SELECT participant_id FROM 
      (SELECT * FROM (SELECT msg_messages.participant_id,msg_participants.convo_id FROM msg_messages,msg_participants WHERE msg_messages.participant_id=msg_participants.id AND participant_id IN 
       (SELECT id FROM msg_participants WHERE convo_id IN (SELECT convo_id FROM msg_participants WHERE prof_id=PROFILE_ID_HERE AND prof_type=PROFILE_TYPE_HERE)) 
      ORDER BY time_cre DESC) AS tbl1 
      GROUP BY tbl1.convo_id) AS tbl2) 

    AND msg_messages.id IN 
     (SELECT id FROM (SELECT * FROM (SELECT msg_messages.id,msg_participants.convo_id FROM msg_messages,msg_participants WHERE msg_messages.participant_id=msg_participants.id AND participant_id IN 
       (SELECT id FROM msg_participants WHERE convo_id IN (SELECT convo_id FROM msg_participants WHERE prof_id=PROFILE_ID_HERE AND prof_type=PROFILE_TYPE_HERE)) 
      ORDER BY time_cre DESC) AS tbl3 
      GROUP BY tbl3.convo_id) AS tbl4) 

我知道怎麼難看/哈克我的代碼,但我在那裏我已經重寫很多次了,我只是想要的東西的工作點。此代碼是...關閉。但它返回msg_participants.id X msg_messages.id的笛卡爾積。對於我爲什麼它返回笛卡爾產品是有道理的,但我不知道如何使這個查詢做我想做的事情。

謝謝!

+0

我覺得你不理解數據庫如何關係的工作。需要有關係。這意味着加入SQL。但是你的模型中似乎沒有關於連接的數據。你怎麼知道一個消息來自哪一個對話。你只知道是誰說的......但人們可以有多個對話。無論如何,你的查詢應該有JOIN語句而不是IN語句。 – Hogan 2014-10-16 19:43:16

+0

我正在使用連接,只是不明確。他們通過msg_messages.participant_id - > msg_participants.id - > msg_participants.convo_id知道消息來自哪個對話。 – William 2014-10-16 19:54:54

回答

0

您可以使用not existsmsg_messages選擇最新行對給定participant_id

select mp.convo_id, mm.id, mp.prof_id, mp.prof_type, mm.message, mm.time_cre 
from msg_participants mp 
join msg_messages mm on mp.id = mm.participant_id 
where mp.prof_id = PROF_ID_HERE 
and mp.prof_type = PROF_TYPE_HERE 
and not exists (
    select 1 from msg_messages mm2 
    where mm2.participant_id = mm.participant_id 
    and mm2.time_cre > mm.time_cre 
)