我有一个名为'mesg'的数据库表,其结构如下:
receiver_id | sender_id |消息|时间戳|读
示例:
2 *(«me)* | 6 *(«nice girl)* | 'I like you, more than ghoti' | yearsago | 1 *(«seen it)*
2 *(«me)* | 6 *(«nice girl)* | 'I like you, more than fish' | now | 1 *(«seen it)*
6 *(«nice girl)* | 2 *(«me)* | 'Hey, wanna go fish?' | yearsago+1sec | 0 *(«she hasn't seen it)*
这是我想要实现的一件非常棘手的事情。
我想得到:最近的消息(= ORDER BY时间DESC)+'联系人姓名'+每个'对话'的时间。
例如:
From: **Bas Kreuntjes** *(« The message from bas is the most recent)*
Hey $py, How are you doing...
From: **Sophie Naarden** *(« Second recent)*
Well hello, would you like to buy my spam? ... *(«I'll work on that later >p)*
To: **Melanie van Deijk** *(« My message to Melanie is 3th)*
And? Did you kiss him? ...
这是一个粗略的输出。
问题:有人可以帮我设置一个好的SQL命令。 这将是while loup
<?php
$sql = "????";
$result = mysql_query($sql);
while($fetch = mysql_fetch_assoc($result)){ ?>
<div class="message-block">
<h1><?php echo($fetch['uname']); ?></h1>
<p><?php echo($fetch['message']); ?></p>
<p><?php echo($fetch['time']); ?></p>
</div>
<?php } ?>
我希望我的解释足够好,如果没有,请告诉我。 请不要介意我的英文和荷兰名字(我自己是荷兰人) 随意纠正我的英语
UPDATE1:我到目前为止最好: 但我不希望出现多个对话...... 你=用户表 m =消息表
SELECT u.uname, m.message, m.receiver_uid, m.sender_uid, m.time
FROM m, u
WHERE (m.receiver_uid = '$myID' AND u.uid = m.sender_uid)
OR (m.sender_uid = '$myID' AND u.uid = m.receiver_uid)
ORDER BY time DESC;
答案 0 :(得分:3)
可爱......但可行。一次建立一个答案。
在示例中给定一个特定的参考用户('我'),您需要找到'我'和另一个人之间的所有消息。对于每个这样的其他人,您希望找到具有最新时间戳的一条消息。
让我们建立会话ID,将所有消息链接在一起。由于我们一次对一方('我')感兴趣,我们可以使用其他人的ID来识别对话。
SELECT m.recipient_uid AS conversation,
m.recipient_uid AS recipient_uid,
m.sender_uid AS sender_uid,
m.timestamp AS timestamp
FROM mesg AS m
WHERE m.sender_uid = '$myID'
UNION
SELECT m.sender_uid AS conversation,
m.recipient_uid AS recipient_uid,
m.sender_uid AS sender_uid,
m.timestamp AS timestamp
FROM mesg AS m
WHERE m.recipient_uid = '$myID'
这使您可以将所有聊天内容与个人一起使用相同的会话ID。
现在您需要通过对话对其进行分组以找到对话和最近的时间;为此,您不需要其他(recipient_uid或sender_uid)列:
SELECT conversation, MAX(timestamp) AS max_timestamp
FROM (SELECT m.recipient_uid AS conversation,
m.timestamp AS timestamp
FROM mesg AS m
WHERE m.sender_uid = '$myID'
UNION
SELECT m.sender_uid AS conversation,
m.timestamp AS timestamp
FROM mesg AS m
WHERE m.recipient_uid = '$myID') AS c
GROUP BY conversation
因此,对于每次对话,我们现在都知道最新的时间戳。我们只需要将这些信息与之前的查询一起加入,以获取大部分细节:
SELECT c.recipient_uid, c.sender_uid, c.timestamp
FROM (SELECT conversation, MAX(timestamp) AS max_timestamp
FROM (SELECT m.recipient_uid AS conversation,
m.timestamp AS timestamp
FROM mesg AS m
WHERE m.sender_uid = '$myID'
UNION
SELECT m.sender_uid AS conversation,
m.timestamp AS timestamp
FROM mesg AS m
WHERE m.recipient_uid = '$myID') AS c
GROUP BY conversation
) AS x
JOIN (SELECT m.recipient_uid AS conversation,
m.recipient_uid AS recipient_uid,
m.sender_uid AS sender_uid,
m.timestamp AS timestamp
FROM mesg AS m
WHERE m.sender_uid = '$myID'
UNION
SELECT m.sender_uid AS conversation,
m.recipient_uid AS recipient_uid,
m.sender_uid AS sender_uid,
m.timestamp AS timestamp
FROM mesg AS m
WHERE m.recipient_uid = '$myID'
) AS c
ON c.conversation = x.conversation AND c.timestamp = x.max_timestamp
既然你说你也想要名字,你可以扩展它以与users表连接两次:
SELECT c.recipient_uid, c.sender_uid, c.timestamp,
u1.uname AS recipient, u2.uname AS sender
FROM (SELECT conversation, MAX(timestamp) AS max_timestamp
FROM (SELECT m.recipient_uid AS conversation,
m.timestamp AS timestamp
FROM mesg AS m
WHERE m.sender_uid = '$myID'
UNION
SELECT m.sender_uid AS conversation,
m.timestamp AS timestamp
FROM mesg AS m
WHERE m.recipient_uid = '$myID') AS c
GROUP BY conversation
) AS x
JOIN (SELECT m.recipient_uid AS conversation,
m.recipient_uid AS recipient_uid,
m.sender_uid AS sender_uid,
m.timestamp AS timestamp
FROM mesg AS m
WHERE m.sender_uid = '$myID'
UNION
SELECT m.sender_uid AS conversation,
m.recipient_uid AS recipient_uid,
m.sender_uid AS sender_uid,
m.timestamp AS timestamp
FROM mesg AS m
WHERE m.recipient_uid = '$myID'
) AS c
ON c.conversation = x.conversation AND c.timestamp = x.max_timestamp
JOIN user AS u1
ON u1.uid = c.recipient_uid
JOIN user AS u2
ON u2.uid = c.sender_uid
那里 - 这很有趣。我不想一次性写出来,但一次建立一块,它不是太吓人(尽管它不是微不足道)。
CREATE TABLE user
(
uid INTEGER NOT NULL PRIMARY KEY,
uname VARCHAR(30) NOT NULL
);
DATETIME YEAR TO SECOND是一种编写TIMESTAMP的有趣方式(在IBM Informix Dynamic Server中 - 这是我测试过的地方)。
CREATE TABLE mesg
(
recipient_uid INTEGER NOT NULL REFERENCES user(uid),
sender_uid INTEGER NOT NULL REFERENCES user(uid),
message VARCHAR(255) NOT NULL,
timestamp DATETIME YEAR TO SECOND NOT NULL,
PRIMARY KEY (recipient_uid, sender_uid, timestamp),
READ CHAR(1) NOT NULL
);
INSERT INTO USER VALUES(2, 'My Full Name');
INSERT INTO USER VALUES(6, 'Her Full Name');
INSERT INTO USER VALUES(3, 'Dag Brunner');
INSERT INTO mesg VALUES(2, 6, 'I like you, more than ghoti', '2008-01-01 00:05:03', 1);
INSERT INTO mesg VALUES(2, 6, 'I like you, more than fish', '2011-01-15 13:45:09', 1);
INSERT INTO mesg VALUES(6, 2, 'Hey, wanna go fish?', '2008-01-01 09:30:47', 0);
INSERT INTO mesg VALUES(2, 3, 'Wanna catch a beer?', '2011-01-14 13:45:09', 1);
INSERT INTO mesg VALUES(3, 2, 'Sounds good to me!!', '2011-01-14 13:55:39', 1);
INSERT INTO mesg VALUES(3, 6, 'Heading home now???', '2010-12-31 12:27:41', 1);
INSERT INTO mesg VALUES(6, 3, 'Yes - on the bus!!!', '2010-12-31 13:55:39', 1);
Conv Recv Send When
3 2 3 2011-01-14 13:45:09
3 3 2 2011-01-14 13:55:39
6 2 6 2008-01-01 00:05:03
6 2 6 2011-01-15 13:45:09
6 6 2 2008-01-01 09:30:47
Conv Most Recent
3 2011-01-14 13:55:39
6 2011-01-15 13:45:09
Recv Send When
3 2 2011-01-14 13:55:39
2 6 2011-01-15 13:45:09
Recv Send When Receiver Sender
3 2 2011-01-14 13:55:39 Dag Brunner My Full Name
2 6 2011-01-15 13:45:09 My Full Name Her Full Name
哇,我不会经常在第一次使用这个复杂的SQL,但在这种情况下,除了在第一次迭代中跳过receiver_uid和recipient_uid之外,它确实首先正常工作时间。
省略'who'(或'我'或'$ myID')参数,我们可以在两个人之间的任何对话中为最新消息提供一般解决方案。会话由较高和较低(或反之亦然)参与者ID标识。否则,它与前一个非常相似。
SELECT c.recipient_uid, c.sender_uid, c.timestamp,
u1.uname AS recipient, u2.uname AS sender
FROM (SELECT conv01, conv02, MAX(timestamp) AS max_timestamp
FROM (SELECT m.recipient_uid AS conv01,
m.sender_uid AS conv02,
m.timestamp AS timestamp
FROM mesg AS m
WHERE m.sender_uid < m.recipient_uid
UNION
SELECT m.sender_uid AS conv01,
m.recipient_uid AS conv02,
m.timestamp AS timestamp
FROM mesg AS m
WHERE m.sender_uid > m.recipient_uid
) AS C
GROUP BY conv01, conv02
) AS x
JOIN (SELECT m.recipient_uid AS conv01,
m.sender_uid AS conv02,
m.recipient_uid AS recipient_uid,
m.sender_uid AS sender_uid,
m.timestamp AS timestamp
FROM mesg AS m
WHERE m.sender_uid < m.recipient_uid
UNION
SELECT m.sender_uid AS conv01,
m.recipient_uid AS conv02,
m.recipient_uid AS recipient_uid,
m.sender_uid AS sender_uid,
m.timestamp AS timestamp
FROM mesg AS m
WHERE m.sender_uid > m.recipient_uid
) AS C
ON c.conv01 = x.conv01 AND c.conv02 = x.conv02
AND c.timestamp = x.max_timestamp
JOIN USER AS u1
ON u1.uid = C.recipient_uid
JOIN USER AS u2
ON u2.uid = C.sender_uid;
Recv Send When Recipient Sender
6 3 2010-12-31 13:55:39 Her Full Name Dag Brunner
2 6 2011-01-15 13:45:09 My Full Name Her Full Name
3 2 2011-01-14 13:55:39 Dag Brunner My Full Name
答案 1 :(得分:0)
这是我想要实现的一件非常棘手的事情。
不是。
您可以使用以下方式获取最后一条消息的时间:
SELECT receiver_id, sender_id, MAX(timestamp) as mtime
FROM mesg
GROUP BY receiver_id, sender_id
(您可能希望添加一个where类来过滤发件人/收件人) 然后得到实际的信息......
SELECT m2.*
FROM mesg m2,
(SELECT receiver_id, sender_id, MAX(timestamp) as mtime
FROM mesg
GROUP BY receiver_id, sender_id) ilv
WHERE m2.sender_id=ilv.seder_id
AND m2.receiver_id=ilv.receiver_id
AND m2.timestamp=ilv.mtime;
然而,这是非常有效的,因为它在桌面上打开2个游标,一个更有效的解决方案(如果你正在运行一个非常旧版本的mysql,唯一的解决方案)是使用max concat trick
我会把它作为练习让你锻炼身体。
答案 2 :(得分:0)
我已经完善了Jonathan脚本:不正确(更新)
第一步有效:
SELECT message, receiver_uid AS receiver, sender_uid AS sender, time, sender_uid AS me, receiver_uid AS contact
FROM messages
WHERE sender_uid = '$me' )
UNION
( SELECT message, receiver_uid AS receiver, sender_uid AS sender, time, receiver_uid AS me, sender_uid AS contact
FROM messages
WHERE receiver_uid = '$me' )
ORDER BY time DESC
它提供了一个很好的清洁列表,告诉我我是否是发件人以及我的联系人。 但是第二部分[MAX()和GROUP BY]的组合并不像我想要的那样工作。
它不会选择最近的会话片段(发送或接收无关紧要)。 它只是选择了第一个新的ID ot遭遇。所以MAX()不起作用。
SELECT m.message, m.receiver, m.sender, max(m.time) « doesn't work well... AS time, m.me, m.contact, u.ufirstname
FROM( ( SELECT message, receiver_uid AS receiver, sender_uid AS sender, time, sender_uid AS me, receiver_uid AS contact
FROM messages
WHERE sender_uid = '$me' )
UNION
( SELECT message, receiver_uid AS receiver, sender_uid AS sender, time, receiver_uid AS me, sender_uid AS contact
FROM messages
WHERE receiver_uid = '$me' )
ORDER BY time DESC) AS m, users AS u
WHERE u.uid = m.contact
GROUP BY m.contact «This one does not do what we want it to do :(
ORDER BY time DESC;
答案 3 :(得分:0)
数据库中的时间需要使用哪种格式的函数MAX()。 Max()不会选择最近的日期,这就是出错的地方。