改进子选择查询

时间:2012-06-10 00:24:40

标签: mysql sql

有没有办法在没有子选择的情况下执行以下查询?

SELECT * FROM 
(
SELECT * FROM messaging_message WHERE recipient_id=4 ORDER BY timestamp DESC
) combined
GROUP BY thread_id HAVING status='unread'

表:

`messaging_message`
 - id
 - thread_id
 - content
 - sender_id
 - recipient_id
 - timestamp
 - status

线程ID是消息的父线程。

更新:在测试目前为止的两个答案时,两个查询都没有生成我需要的结果。

查询应仅返回消息thread ='unread'中最新消息的结果。以下两个查询都返回了包含status ='unread'消息的任何线程的最顶层结果。

我要做的是像任何电子邮件收件箱,例如Gmail。假设收件箱在第一页上显示25个主题。我想强调那些具有status ='unread'的最新消息的线程(忽略任何早于最新消息的消息的状态)。

这也是我在订购结果上使用GROUP BY的原因,因此我只能得到最新的结果,并且从这些结果中看出哪一个有状态='未读'

(请注意,我还将上述查询中的状态从“已删除”更改为“未读”,因此我可以更清楚地说明这一点。)

2 个答案:

答案 0 :(得分:3)

你的查询是一个MySQL黑客攻击。 SQL标准不允许order by处于该位置。我甚至不确定它是否会在MySQL中保持一致。话虽如此,您的版本相当清晰,并且可能优于更严格的版本。

例如,更正式的编写查询的方式是:

select  *
from    (
        select  distinct thread_id
        from    messaging_message
        where   recipient_id = 4
        ) thread
join    messaging_message mm
on      mm.id =
        (
        select  mm2.id
        from    messaging_message mm2
        where   thead.thread_id = mm2.thread_id
        order by
                mm2.timestamp desc
        limit   1
        )
where   mm.status = 'unread'

答案 1 :(得分:2)

所以要清楚,你试图在每个帖子中检索最近删除的邮件的详细信息,其中该邮件的收件人是user_id 4 ...是否正确?如果是这样,这个问题类似于你发布的问题here,似乎你已经将你的messagestatus表合并到你的消息表中了(好!)。所以这是我调整后的答案:

SELECT 
    b.*
FROM 
    messaging_messagethread a
INNER JOIN 
    messaging_message b ON a.id = b.thread_id
WHERE 
    b.timestamp =
    (
        SELECT MAX(timestamp)
        FROM messaging_message
        WHERE thread_id = a.id
    )
    AND b.status = 'unread'
    AND b.recipient_id = 4

在这里,我们使用correlated subquery来提取每个帖子的最新消息的时间戳。

然后我们检查该消息的状态是否为“未读”。

最后,在WHERE子句的第三个条件中,我们只选择上次删除的消息的收件人为user_id 4的线程。