我的目标是获取用户A与其他朋友的所有最后消息。
我有一位朋友和消息
朋友表如下
+---------+-----------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+-----------------+------+-----+---------+----------------+
| id | int(6) unsigned | NO | PRI | NULL | auto_increment |
| user1 | int(6) unsigned | NO | MUL | NULL | |
| user2 | int(6) unsigned | NO | MUL | NULL | |
| pending | tinyint(1) | NO | | NULL | |
+---------+-----------------+------+-----+---------+----------------+
消息表如下
+-----------------+-----------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+-----------------+------+-----+-------------------+-----------------------------+
| id | int(6) unsigned | NO | PRI | NULL | auto_increment |
| sender | int(6) unsigned | NO | MUL | NULL | |
| receiver | int(6) unsigned | NO | MUL | NULL | |
| message | varchar(255) | NO | | NULL | |
| message_read | tinyint(1) | NO | | NULL | |
| message_visible | int(6) | YES | | NULL | |
| message_date | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+-----------------+-----------------+------+-----+-------------------+-----------------------------+
这是个人资料表
+----------+-----------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-----------------+------+-----+---------+----------------+
| id | int(6) unsigned | NO | PRI | NULL | auto_increment |
| user_id | int(6) unsigned | NO | MUL | NULL | |
| nickname | varchar(50) | YES | UNI | NULL | |
| email | varchar(50) | YES | | NULL | |
| image | mediumblob | YES | | NULL | |
+----------+-----------------+------+-----+---------+----------------+
根据要求,这是消息的数据集
+----+--------+----------+-------------------------------------------------------------+--------------+-----------------+---------------------+
| id | sender | receiver | message | message_read | message_visible | message_date |
+----+--------+----------+-------------------------------------------------------------+--------------+-----------------+---------------------+
| 1 | 1 | 2 | test | 1 | NULL | 2017-09-30 21:10:15 |
| 2 | 1 | 2 | test | 1 | NULL | 2017-09-30 21:10:16 |
| 3 | 2 | 1 | test | 1 | NULL | 2017-09-29 21:10:15 |
| 4 | 2 | 1 | test | 1 | NULL | 2017-09-30 21:10:14 |
| 5 | 1 | 4 | test | 1 | NULL | 2017-09-30 21:10:14 |
| 6 | 1 | 4 | test | 1 | NULL | 2017-09-30 21:10:15 |
| 7 | 4 | 1 | test | 1 | NULL | 2017-09-29 21:10:15 |
| 8 | 4 | 1 | test | 1 | NULL | 2017-09-30 21:10:17 |
| 9 | 5 | 1 | test | 1 | NULL | 2017-09-30 21:10:18 |
| 10 | 5 | 1 | test | 1 | NULL | 2017-09-30 21:10:15 |
| 11 | 1 | 5 | test | 1 | NULL | 2017-09-30 21:10:14 |
| 12 | 1 | 5 | test | 1 | NULL | 2017-09-30 21:10:15 |
| 13 | 1 | 7 | test | 1 | 7 | 2017-09-30 21:10:15 |
| 14 | 2 | 3 | test | 1 | NULL | 2017-09-30 21:10:15 |
| 15 | 2 | 3 | test | 1 | NULL | 2017-09-30 21:10:14 |
| 16 | 3 | 2 | test | 1 | NULL | 2017-09-30 21:10:17 |
| 17 | 3 | 2 | test | 1 | NULL | 2017-09-30 21:10:15 |
| 18 | 3 | 4 | test | 1 | NULL | 2017-09-30 21:10:15 |
| 19 | 3 | 4 | test | 1 | NULL | 2017-09-30 21:10:14 |
| 20 | 4 | 3 | test | 1 | NULL | 2017-09-30 21:10:17 |
| 21 | 4 | 3 | test | 1 | NULL | 2017-09-30 21:10:15 |
| 22 | 2 | 4 | test | 1 | NULL | 2017-09-30 21:10:15 |
| 23 | 2 | 4 | test | 1 | NULL | 2017-09-30 21:10:14 |
| 24 | 4 | 2 | test | 1 | NULL | 2017-09-30 21:10:17 |
| 25 | 4 | 2 | test | 1 | NULL | 2017-09-30 21:10:15 |
| 26 | 11 | 4 | test1 | 1 | NULL | 2017-10-19 13:24:53 |
| 27 | 11 | 6 | test2 | 1 | NULL | 2017-10-19 19:56:46 |
| 28 | 11 | 7 | test3 | 1 | NULL | 2017-10-19 12:30:38 |
| 29 | 4 | 11 | test1_response | 1 | NULL | 2017-10-19 21:03:27 |
| 30 | 6 | 11 | test2_response | 1 | NULL | 2017-10-19 21:03:34 |
| 31 | 13 | 6 | test1 | 1 | NULL | 2017-10-20 09:36:09 |
| 32 | 13 | 7 | test1 | 1 | NULL | 2017-10-20 09:36:13 |
| 33 | 11 | 13 | test11 | 1 | NULL | 2017-10-20 09:36:21 |
| 34 | 13 | 11 | test11_response | 1 | NULL | 2017-10-20 09:41:27 |
| 35 | 1013 | 2 | test | 1 | NULL | 2018-03-29 13:35:31 |
| 36 | 2 | 1013 | Longer text message test, and I wish this works beautifully | 1 | NULL | 2018-03-29 15:12:33 |
| 37 | 1013 | 2 | Longer text message test, and I wish this works beautifully | 1 | NULL | 2018-03-29 15:17:40 |
| 38 | 1013 | 2 | Longer text message test, and I wish this works beautifully | 1 | NULL | 2018-03-29 15:41:55 |
| 39 | 1015 | 2 | What's up | 1 | NULL | 2018-04-17 16:33:29 |
| 40 | 2 | 1015 | What up? | 1 | NULL | 2018-04-17 16:33:29 |
| 42 | 2 | 1015 | What's up | 0 | NULL | 2018-04-17 16:33:29 |
+----+--------+----------+-------------------------------------------------------------+--------------+-----------------+---------------------+
以下是朋友的数据集
+-----+-------+-------+---------+
| id | user1 | user2 | pending |
+-----+-------+-------+---------+
| 1 | 1 | 2 | 0 |
| 3 | 1 | 5 | 0 |
| 4 | 6 | 1 | 0 |
| 6 | 2 | 5 | 0 |
| 7 | 3 | 5 | 0 |
| 8 | 6 | 2 | 0 |
| 9 | 6 | 1 | 0 |
| 10 | 5 | 4 | 0 |
| 11 | 4 | 1 | 0 |
| 12 | 1 | 7 | 1 |
| 19 | 12 | 1 | 1 |
| 20 | 12 | 2 | 0 |
| 22 | 12 | 4 | 0 |
| 23 | 12 | 11 | 0 |
| 25 | 6 | 11 | 0 |
| 26 | 7 | 11 | 0 |
| 27 | 7 | 12 | 0 |
| 28 | 6 | 13 | 0 |
| 29 | 7 | 13 | 0 |
| 30 | 11 | 13 | 0 |
| 31 | 1013 | 2 | 0 |
| 39 | 1015 | 2 | 0 |
| 104 | 1015 | 1021 | 1 |
+-----+-------+-------+---------+
以下是个人资料数据片段
+------+---------+----------+-------+-------+
| id | user_id | nickname | email | image |
+------+---------+----------+-------+-------+
| 1 | 1 | user1 | | NULL |
| 2 | 2 | user2 | NULL | NULL |
| 3 | 3 | user3 | NULL | NULL |
| 4 | 4 | user4 | NULL | NULL |
| 1014 | 1018 | user1019 | NULL | NULL |
| 1015 | 1019 | user1020 | NULL | NULL |
| 1016 | 1020 | user1021 | NULL | NULL |
| 1017 | 1021 | user1022 | NULL | NULL |
+------+---------+----------+-------+-------+
我编写了我的陈述,引用了StackOverFlow上发布的一些很棒的答案
这是我的sql语句:
SELECT msg.message, msg.message_read, msg.message_date,
CASE WHEN msg.receiver = 1013
THEN (SELECT nickname FROM profile WHERE user_id = msg.sender)
ELSE (SELECT nickname FROM profile WHERE user_id = msg.receiver)
END AS name,
CASE WHEN msg.receiver = 1013
THEN (SELECT image FROM profile WHERE user_id = msg.sender)
ELSE (SELECT image FROM profile WHERE user_id = msg.receiver)
END AS image
FROM message msg
JOIN
(SELECT user, max(message_date) m
FROM
((SELECT id, receiver user, message_date FROM message WHERE sender = 1015 AND (message_visible =1 OR message_visible IS NULL))
UNION
(SELECT id, sender user, message_date FROM message WHERE receiver = 1015 AND (message_visible =1 OR message_visible IS NULL))) m1 GROUP BY user) m2 ON
((sender = 1015 AND receiver = user) OR (sender = user AND receiver = 1015)) AND (message_date = m) ORDER BY message_date desc;
我得到的结果是
+-----------+--------------+---------------------+----------+-------+
| message | message_read | message_date | name | image |
+-----------+--------------+---------------------+----------+-------+
| What's up | 1 | 2018-04-17 16:33:29 | user2 | NULL |
| What up? | 1 | 2018-04-17 16:33:29 | user1016 | NULL |
| What's up | 0 | 2018-04-17 16:33:29 | user1016 | NULL |
+-----------+--------------+---------------------+----------+-------+
我想只得到其中的一个..哪一个并不重要。当然,如果有更多用户,会有更多消息。问题是我有相同的message_date。虽然同时发送消息似乎难以置信,但我至少想学习如何控制这种情况。
答案 0 :(得分:3)
首先,您与其他人一起从您的用户A获取消息。我没有包含消息不可见时的条件,因为逻辑从问题中看不清楚。你必须自己添加它。
SQL DEMO (没有个人资料表)
SELECT m.message,
m.message_read,
m.message_date,
CASE WHEN m.sender = @userA_ID
THEN m.receiver
ELSE m.sender
END as friend_id,
CASE WHEN m.sender = @userA_ID
THEN p2.nickname
ELSE p1.nickname
END as name,
CASE WHEN m.sender = @userA_ID
THEN p2.image
ELSE p1.image
END as image
FROM message as m
JOIN profile as p1
ON m.sender = p1.user_id -- sender
JOIN profile as p2
ON m.receiver = p1.user_id -- receiver
WHERE @userA_ID IN (m.sender, m.receiver)
现在您使用变量按朋友和日期对消息进行排序,请注意您使用friend_id
以防两个朋友的姓名相同。
SELECT t.*,
@rn := if(@friend = t.friend_id,
@rn + 1,
if( @friend := t.friend_id, 1, 1)
) as rn
FROM ( ** previous_query ** ) as t
CROSS JOIN ( SELECT @rn := 0, @friend := 0 ) as var
ORDER BY t.friend_id, t.message_date desc
请注意,您可以添加另一个条件,以便在相同日期处理关系
最后,您使用rn = 1
SELECT *
FROM ( ** second query **) q
WHERE q.rn = 1