我在SQL语句中运行了太多子查询吗?

时间:2011-06-22 15:29:05

标签: mysql sql database design-patterns

我有以下表格:

users:
    user_id
    user_name

message:
    message_id
    thread_id
    to_id
    from_id
    title
    message_text
    message_date        
    status

我运行的查询的所需结果是列出titlethread_id中最近的线程中最新消息的username并对结果进行排序按date降序排列。我最有可能一次列出大约10到20个结果。

我提出的SQL查询似乎到目前为止这样做,但我觉得我已经过度复杂了,并且可能有更优化的方式来编写我的查询。

    SELECT personal_messages.message_id, 
           personal_messages.thread_id, 
           personal_messages.body, 
           users.username
    FROM users, personal_messages
    WHERE message_id IN 
        (SELECT MAX(message_id) from personal_messages GROUP BY thread_id)
    AND users.id IN 
        (SELECT users.id FROM users WHERE users.id = personal_messages.from_id)
    ORDER BY personal_messages.message_date DESC

此外,如果有人知道如何获取具有相同count的所有邮件的thread_id,那就太棒了!

任何提示都将不胜感激!

4 个答案:

答案 0 :(得分:2)

其中一个子选择可能是不必要的

SELECT personal_messages.message_id, personal_messages.thread_id, personal_messages.body, users.username
FROM users INNER JOIN personal_messages ON (users.id = personal_messages.from_id)
WHERE message_id IN (SELECT MAX(message_id) from personal_messages GROUP BY thread_id)
ORDER BY personal_messages.message_date DESC    

编辑:此外,如果有人知道如何获得具有相同thread_id的所有消息的计数,那将是非常棒的!

SELECT MAX(message_id), COUNT(message_id) FROM personal_messages GROUP BY thread_id

答案 1 :(得分:0)

SELECT tbl.message_id, personal_messages.thread_id
       , personal_messages.body, users.username
FROM users u
JOIN personal_messages tbl on tbl. from_id = u.UsersId
WHERE tbl.message_id IN (SELECT MAX(message_id) from personal_messages 
GROUP BY thread_id)
ORDER BY personal_messages.message_date DESC

答案 2 :(得分:0)

我认为您的查询中没有太多子查询,但可以更优化地编写。我认为以下查询应该同样有效:

SELECT `PM`.`message_id`, `PM`.`thread_id`, `PM`.`body`, `U`.`username`
FROM `users` `U`
INNER JOIN `personal_messages` `PM` ON `PM`.`from_id` = `U`.`user_id`
ORDER BY `PM`.`message_date` DESC;

我在您的查询中发现的问题是:

  1. 第一个子查询 - SELECT MAX(message_id) from personal_messages GROUP BY thread_id - 将始终返回单个结果集,因此使用IN没有意义
  2. 对于第二个子查询 - SELECT users.id FROM users WHERE users.id = personal_messages.from_id - 您可以使用INNER JOIN,就像在我的示例中一样
  3. 希望以上有所帮助。

    另外,我不确定您确实要检索哪些信息。但上面的查询应该为您提供最新消息的详细信息,以及其线程ID和用户名。

    EDITED 查询为每个帖子选择一条最新消息:

    SELECT *
    FROM (
        SELECT `PM`.`message_id`, `PM`.`thread_id`, `PM`.`body`, `U`.`username`
        FROM `users` `U`
        INNER JOIN `personal_messages` `PM` ON `PM`.`from_id` = `U`.`user_id`
        ORDER BY `PM`.`message_date` DESC;
    ) `TT`
    GROUP BY `TT`.`thread_id`;
    

答案 3 :(得分:0)

你已经拥有的非常好。如果您想使用一个查询完成所有操作,则可以将COUNT(message_id) GROUP BY thread_id作为获取MAX(message_id) GROUP BY thread_id的同一子选择的一部分:

SELECT personal_messages.message_id,
       personal_messages.thread_id,
       personal_messages.body,
       users.username,
       thread.countmessages
FROM personal_messages
JOIN users ON users.id=personal_messages.from_id
JOIN
     (SELECT COUNT(message_id) countmessages, 
             MAX(message_id) maxmessage_id
         FROM personal_messages
         GROUP BY thread_id) AS thread 
     ON thread.maxmessage_id=personal_messages.message_id
ORDER BY personal_messages.message_date DESC