Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ms-access/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
这在一个快速的mysql查询中是可能的吗?_Mysql_Group By - Fatal编程技术网

这在一个快速的mysql查询中是可能的吗?

这在一个快速的mysql查询中是可能的吗?,mysql,group-by,Mysql,Group By,我有三个表,我需要所有表的不同数据。遗憾的是,我还需要能够提取最新的行 这是我的桌子: 消息:我只是将消息的内容存储在一个表中,因为一条文本可以发送给多个用户 +------------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+--------

我有三个表,我需要所有表的不同数据。遗憾的是,我还需要能够提取最新的行

这是我的桌子:

消息:我只是将消息的内容存储在一个表中,因为一条文本可以发送给多个用户

+------------+------------------+------+-----+---------+----------------+
| Field      | Type             | Null | Key | Default | Extra          |
+------------+------------------+------+-----+---------+----------------+
| message_id | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| content    | varchar(255)     | NO   |     | 0       |                |
+------------+------------------+------+-----+---------+----------------+
对话:此表仅反映两个用户之间的单个对话

+-----------------+------------------+------+-----+---------+----------------+
| Field           | Type             | Null | Key | Default | Extra          |
+-----------------+------------------+------+-----+---------+----------------+
| partner_id      | int(10) unsigned | NO   | MUL | NULL    |                |
| conversation_id | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| expedition_id   | int(11)          | NO   |     | NULL    |                |
| active          | tinyint(4)       | NO   |     | 1       |                |
+-----------------+------------------+------+-----+---------+----------------+
对话消息:此表存储有关实际交换消息的信息

+-----------------+------------------+------+-----+---------+-------+
| Field           | Type             | Null | Key | Default | Extra |
+-----------------+------------------+------+-----+---------+-------+
| message_id      | int(11) unsigned | NO   | PRI | NULL    |       |
| receiver_id     | int(11) unsigned | NO   | PRI | NULL    |       |
| conversation_id | int(11) unsigned | NO   | MUL | NULL    |       |
| status          | tinyint(4)       | NO   |     | NULL    |       |
| timestamp       | datetime         | YES  |     | NULL    |       |
+-----------------+------------------+------+-----+---------+-------+
我现在要做的是选择每个对话中的最新消息,并从该消息中获取内容。(听起来很简单,但没有找到简单的解决方案)。我尝试了以下几点:

SELECT max(c_m.message_id), m.content, c_m.`status` 
FROM expedition_conversations e_c, conversation_messages c_m 
    INNER JOIN messages m ON m.message_id = c_m.message_id 
WHERE e_c.expedition_id = 1 AND (c_m.conversation_id = e_c.conversation_id)      
GROUP BY c_m.conversation_id;
不幸的是,由于
groupby
在大多数情况下似乎在内部选择第一个插入的行,因此我从
messages
表中选择的
content
是错误的,而从
conversation\u messages
中选择的
message\u id
是正确的

知道如何在一个查询中执行此操作吗?如果您有任何改变表格结构的建议,我也将不胜感激


提前感谢。

这是可能的,因为您使用的
自动增量
意味着最高id属于最新消息:

SELECT
  messages.*,
FROM
  conversations
  INNER JOIN (
    SELECT conversation_id, MAX(message_id) AS maxmsgid
    FROM conversation_messages
    GROUP BY conversation_id
  ) AS latest ON latest.conversation_id=conversations.id
  INNER JOIN messages
    ON messages.message_id=latest.maxmsgid
WHERE 
  1=1 -- whatever you want or need!

既然这个查询一定很慢,您可能需要考虑几个选项:

  • 投入硬件:使用足够的RAM并配置MySQL,以便尽可能晚地进入interims表的磁盘
  • 使用非规范化并在插入后启用
    触发
    消息
    更新
    对话\u消息
    上保存最新消息ID的字段

您可能想尝试此版本:

SELECT c_m.message_id, m.content, c_m.`status` 
FROM expedition_conversations e_c join
     conversation_messages c_m 
     ON c_m.conversation_id = e_c.conversation_id INNER JOIN
     messages m
     ON m.message_id = c_m.message_id 
WHERE e_c.expedition_id = 1 AND
      NOT EXISTS (SELECT 1
                  FROM conversation_messages cm2
                  WHERE cm2.conversation_id = c_m.conversation_id AND
                        cm2.timestamp > c_m.timestamp
                 ) 
为了提高性能,您需要在
conversation\u消息(conversation\u id,timestamp)

上建立索引,请尝试以下小技巧:

SELECT c_m.message_id, m.content, c_m.status
FROM expedition_conversations e_c
JOIN (select * from (
    select * from conversation_messages
    order by message_id desc) x
  group by conversation_id) c_m ON c_m.conversation_id = e_c.conversation_id
INNER JOIN messages m ON m.message_id = c_m.message_id 
WHERE e_c.expedition_id = 1

如果mysql-5.6.19,这将在您的版本上起作用,并且应该比其他方法更有效

您使用的是什么版本的mysql?谢谢。我会记住你的两个选择。向上投票,而不是接受答案,因为我确实使用了上述解决方案;)