MySQL SELECT * FROM ... WHERE ... ORDER BY '哪一个在另一个表中有最新记录'
Posted
技术标签:
【中文标题】MySQL SELECT * FROM ... WHERE ... ORDER BY \'哪一个在另一个表中有最新记录\'【英文标题】:MySQL SELECT * FROM ... WHERE ... ORDER BY 'which one has the latest record in other table 'MySQL SELECT * FROM ... WHERE ... ORDER BY '哪一个在另一个表中有最新记录' 【发布时间】:2014-02-23 23:31:21 【问题描述】:我有以下表格:
chats:
+--------+-------------+--------------+--------------+---------------------+
| chatID | firstPerson | secondPerson | chatAccepted | creationDate |
+--------+-------------+--------------+--------------+---------------------+
| 1 | 59 | 52 | 1 | 31-01-2014 09:32:37 |
| 2 | 59 | 12 | 0 | 28-01-2014 11:07:25 |
| 3 | 34 | 59 | 1 | 28-01-2014 08:50:48 |
| 4 | 78 | 59 | 1 | 26-01-2014 03:58:12 |
+--------+-------------+--------------+--------------+---------------------+
messages:
+-----------+-------------+--------+----------+------------+---------------------+
| messageID | messageText | chatID | senderID | receiverID | creationDate |
+-----------+-------------+--------+----------+------------+---------------------+
| 1 | Lorum... | 1 | 59 | 52 | 31-01-2014 09:32:37 |
| 2 | Ipsum... | 1 | 52 | 59 | 28-01-2014 11:07:25 |
| 3 | Dollar... | 3 | 34 | 59 | 28-01-2014 08:50:48 |
| 4 | Sit... | 3 | 59 | 34 | 31-01-2014 11:09:48 |
+-----------+-------------+--------+----------+------------+---------------------+
我想要得到的结果是 chatID,其中(firstPerson = 59 或 secondPerson = 59)和 chatAccepted = 1。现在我无法弄清楚:我希望结果按“哪个”排序有最新消息”。
我尝试了很多不同的东西,其中之一是:
"SELECT chats.chatID, chats.firstPerson, chats.secondPerson, str_to_date(messages.creationDate,'%d-%m-%Y %H:%i:%s') AS cdate
FROM chats
INNER JOIN messages
ON chats.chatID=messages.chatID
WHERE chats.chatAccepted = 1 AND messages.receiverID = 59
UNION SELECT chats.chatID, chats.firstPerson, chats.secondPerson, str_to_date(messages.creationDate,'%d-%m-%Y %H:%i:%s') AS cdate
FROM chats
INNER JOIN messages
ON chats.chatID=messages.chatsID
WHERE chats.chatAccepted = 1 AND messages.senderID = 59
ORDER BY cdate desc"
这就像一个魅力,除了还没有消息的时候。比它只是结果没有记录。但我需要知道该聊天是否被接受,否则他们甚至无法开始聊天。
非常欢迎任何帮助。 如果您需要更多信息,请告诉我!
更新:所以在这种情况下我至少想要的是:
+--------+
| chatID |
+--------+
| 3 |
| 1 |
| 4 |
+--------+
这是因为 chatID '3' 有链接到它的最新消息。 chatID '4' 还没有消息,但它是一个接受的聊天,所以它应该在结果中。
【问题讨论】:
想要的结果实际上是什么样的? 您的totla操作要查找最新消息非常昂贵 另外,“聊天”的所有参与者都不会收到一条消息吗? 我不明白为什么这是一个坏问题,那么为什么是 -1?不管怎样@Strawberry 是两个人之间的聊天,只有在两个人都接受聊天时才会显示。 我的观点是,如果聊天只存在于两个人之间,并且我们知道消息发送者是谁,那么消息接收者是多余的。 【参考方案1】:SELECT c.chatID, c.firstPerson, c.secondPerson, str_to_date(m.creationDate,'%d-%m-%Y %H:%i:%s') AS cdate
FROM chats c left join messages m on c.chatID=m.chatID
WHERE c.chatAccepted = 1 AND
59 in (m.senderID, m.receiverID)
ORDER BY m.creationDate desc
【讨论】:
感谢 Paul,这看起来很轻巧,很有说服力。但我得到了错误:#1054 - 'on 子句'中的未知列'chats.chatID' 对不起,我忘了想.. 在我更改了 c 中的聊天和 d 中的消息后,它起作用了。但我没有得到任何结果。所以出了点问题,但是找不到什么。 我现在得到了一个结果,我删除了 '59 in...' 但现在 cdate 为空,可能是因为每个聊天有更多消息,因此它获得了超过 1 个 creationDate。我确定 str_to_date(m.creationDate,'%d-%m-%Y %H:%i:%s') 工作正常。【参考方案2】:要保持聊天也没有消息,你需要LEFT JOIN
,那么你应该决定让聊天没有消息,假设你想使用聊天创建日期,然后使用 COALESCE
功能选择聊天创建日期,其中没有消息(消息创建日期为 NULL)。
通过这种方式,您可以拥有多个聊天条目,其中包含更多消息,而不是您还必须在 cDate 上使用聚合函数 MAX
才能只有最后一条消息条目:
SELECT c.chatID,
c.firstPerson,
c.secondPerson,
str_to_date(MAX(COALESCE(m.creationDate, c.creationDate)),'%d-%m-%Y %H:%i:%s') AS cdate
FROM chats AS c LEFT OUTER JOIN
messages AS m ON c.ChatID = m.ChatID
WHERE c.Accepted = 1 AND (c.firstPerson=59 OR c.SecondPerson=59)
GROUP BY c.chatID, c.firstPerson, c.secondPerson
ORDER BY cdate DESC
我不确定在 mysql 中将 str_to_date 函数应用于聚合字段是否有效,在否定的情况下,查询应重写为:
SELECT chatID,
firstPerson,
secondPerson,
str_to_date(cdate,'%d-%m-%Y %H:%i:%s') AS cdate
FROM (SELECT c.chatID,
c.firstPerson,
c.secondPerson,
MAX(COALESCE(m.creationDate, c.creationDate)) AS cdate
FROM chats AS c LEFT OUTER JOIN
messages AS m ON c.ChatID = m.ChatID
WHERE c.Accepted = 1 AND (c.firstPerson=59 OR c.SecondPerson=59)
GROUP BY c.chatID, c.firstPerson, c.secondPerson
ORDER BY cdate DESC) AS devTbl
希望对你有帮助
【讨论】:
以上是关于MySQL SELECT * FROM ... WHERE ... ORDER BY '哪一个在另一个表中有最新记录'的主要内容,如果未能解决你的问题,请参考以下文章
试图制作返回 mysql 'SELECT * FROM' 结果的函数,最终返回 undefined