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 —— 基本查询方法

mysql 选择在一个table不在另一个table的数据

Mysql“select * from”不返回所有行

试图制作返回 mysql 'SELECT * FROM' 结果的函数,最终返回 undefined

mysql之数据查询SELECT * FROM students; SELECT * FROM classes;

Mysql: SELECT * FROM .... 没有一个字段