MySQL GROUP BY表现奇怪,没有返回预期的结果

时间:2016-06-22 16:51:32

标签: mysql group-by

我试图用 ID 258776 返回该行,这是我迄今为止尝试过的...

这是我的例子,我使用AND msg.uid来获取一个消息线程。我想返回每个线程的最新帖子,因此在示例中只有2个消息用于1个线程,我希望返回 ID 258776 的行。

没有GROUP BY:

SELECT main.id, main.message_id, main.inbox_id, main.uid, main.body, main.created_at FROM (
                SELECT i.id as inbox_id, i.message_id, msg.* FROM inbox AS i
                INNER JOIN message AS msg ON i.message_id = msg.id
                WHERE i.profile_id = 2135
                AND i.is_sent = 0
                AND i.is_deleted = 0
                #AND msg.uid = '570cc3a568402'
                ORDER BY msg.updated_at DESC
            ) AS main #GROUP BY main.uid


= ID =  =MSG =  =INB =  = UID       =   = BD =   = CREATED         =  
258776  258776  524785  570cc3a568402   wtf      2016-06-22 11:34:29  
217149  217149  438907  570cc3a568402   <br />   2016-04-12 11:45:09  

尝试使用GROUP BY

SELECT main.id, main.message_id, main.inbox_id, main.uid, main.body, main.created_at FROM (
                SELECT i.id as inbox_id, i.message_id, msg.* FROM inbox AS i
                INNER JOIN message AS msg ON i.message_id = msg.id
                WHERE i.profile_id = 2135
                AND i.is_sent = 0
                AND i.is_deleted = 0
                #AND msg.uid = '570cc3a568402'
                ORDER BY msg.updated_at DESC
            ) AS main GROUP BY main.uid

= ID =  =MSG =  =INB =  = UID       =   = BD =   = CREATED         =  
217149  217149  438907  570cc3a568402   <br />   2016-04-12 11:45:09  

切换到ASC但GROUP BY会给出相同的结果吗?

SELECT main.id, main.message_id, main.inbox_id, main.uid, main.body, main.created_at FROM (
                SELECT i.id as inbox_id, i.message_id, msg.* FROM inbox AS i
                INNER JOIN message AS msg ON i.message_id = msg.id
                WHERE i.profile_id = 2135
                AND i.is_sent = 0
                AND i.is_deleted = 0
                #AND msg.uid = '570cc3a568402'
                ORDER BY msg.updated_at ASC
            ) AS main GROUP BY main.uid

= ID =  =MSG =  =INB =  = UID       =   = BD =   = CREATED         =  
217149  217149  438907  570cc3a568402   <br />   2016-04-12 11:45:09

如果我不需要使用INNER连接,我认为它应该可以正常工作? :(

修改

此处还有来自message表和inbox表格的更多数据。

message

= ID =  =FROMID=  = UID       = = TITLE = = BODY =  = CREATED         =
258776  52169     570cc3a568402 RE: RE:   wtf       2016-06-22 11:34:29  
258775  2135      570cc3a568402 RE: You   Testtest  2016-06-22 11:31:29 
258774  34833     576a590fdf9e5 RE: Sure  < 3 < 3   2016-06-22 11:24:08  
258773  34833     576a590fdf9e5 RE: Sure  sok       2016-06-22 11:23:57     
258772  34833     576a590fdf9e5 RE: Sure  hey hey   2016-06-22 11:23:46     

inbox

= ID =  = PROFILE =   = MSG_ID =   = IS_SENT = = IS_READ = = IS_DELETED =
524785  2135          258776       0           0           0
524784  52169         258776       1           1           0
524783  52169         258775       0           1           0
524782  2135          258775       1           0           0
524781  2135          258774       0           1           0

3 个答案:

答案 0 :(得分:1)

如果您想要符合条件的最大ID,则应使用

SELECT main.id, main.message_id, main.inbox_id, main.uid, main.body, main.created_at 
    FROM (
            SELECT i.id as inbox_id, i.message_id, msg.* FROM inbox AS i
            INNER JOIN message AS msg ON i.message_id = msg.id
            WHERE i.id = (    

                SELECT max(i.id)  FROM inbox AS i
                INNER JOIN message AS msg ON i.message_id = msg.id
                WHERE i.profile_id = 2135
                AND i.is_sent = 0
                AND i.is_deleted = 0
                AND msg.uid = '570cc3a568402'

            )


        ) AS main

像评论中所说的分组是针对aggegatte函数(使用multiplr结果)你没有这个然后你不需要

答案 1 :(得分:0)

重申我原来的评论;除非你试图实现一些不寻常的逻辑,否则我真的不需要GROUP BY或子查询;只需使用LIMIT

SELECT msg.id, i.message_id, i.id as inbox_id, msg.uid, msg.body, msg.created_at
FROM inbox AS i
INNER JOIN message AS msg ON i.message_id = msg.id
WHERE i.profile_id = 2135
   AND i.is_sent = 0
   AND i.is_deleted = 0
   AND msg.uid = '570cc3a568402'
ORDER BY msg.updated_at DESC
LIMIT 1

编辑:通过附加信息,您可以通过查询获得所需内容:

SELECT m.id, i.message_id, i.id as inbox_id, m.uid, m.body, m.created_at
FROM 
(SELECT uid, MAX(updated_at) AS updated_at
FROM message
GROUP BY uid) AS lastMs
INNER JOIN message AS m USING(uid, updated_at)
INNER JOIN inbox AS i ON m.id = i.message_id

我可以通过此查询或任何可能的解决方案看到的主要问题是,到目前为止已经描述过的问题是,可能存在多条具有相同uid AND {{1}的消息}};在这种情况下,将为updated_at返回多个结果。

答案 2 :(得分:0)

我最终使用PHP来解决我的问题,通过执行PDO查询来选择所有消息,然后遍历这些结果以获得按线程ID(uid)分组的简单消息ID数组......

$pdo = Doctrine_Manager::connection();
$results = $pdo->execute('SELECT i.id, i.message_id, msg.uid FROM inbox AS i
            INNER JOIN message AS msg ON i.message_id = msg.id
            WHERE i.profile_id = :profile_id
            AND i.is_sent = :is_sent
            AND i.is_deleted = :is_deleted
            ORDER BY msg.created_at ASC', [
        ':profile_id' => $address->getId(),
        ':is_sent' => 0,
        ':is_deleted' => 0,
    ])->fetchAll();

$whereIn = [];

foreach ($results as $key => $value) {
    $whereIn[$value['uid']] = $value['id'];
}

return $this
        ->getBaseMessageBoxQuery()
        ->addWhere('i.profile_id = ?', $address->getId())
        ->andWhere('i.is_sent = 0')
        ->andWhere('i.is_deleted = 0')
        ->andWhereIn('i.id', array_values($whereIn))
        ->addGroupBy('msg.uid')
        ->orderBy('msg.created_at DESC');