Я выполняю слишком много подзапросов в своем операторе SQL? - PullRequest
1 голос
/ 22 июня 2011

У меня есть следующие таблицы:

users:
    user_id
    user_name

message:
    message_id
    thread_id
    to_id
    from_id
    title
    message_text
    message_date        
    status

Желаемый результат запускаемого мной запроса - перечислить title самого последнего сообщения из самых последних тем, длинное с thread_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 ]

2 голосов
/ 22 июня 2011

Один из подвыборов может быть ненужным

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    

Редактировать: Кроме того, если кто-нибудь знает способ получить количество всех сообщений с одинаковым идентификатором потока, это было бы здорово!

SELECT MAX(message_id), COUNT(message_id) FROM personal_messages GROUP BY thread_id
0 голосов
/ 27 июня 2011

То, что у вас уже есть, довольно хорошо.Если вы хотите сделать все это одним запросом, вы можете получить 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
0 голосов
/ 22 июня 2011

Не думаю, что в вашем запросе слишком много подзапросов, но его можно написать более оптимально. Я думаю, что следующий запрос должен работать одинаково хорошо:

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, как в моем примере

Надеюсь, что вышеупомянутое помогает.

Кроме того, я не уверен, какую информацию вы на самом деле пытаетесь получить. Но приведенный выше запрос должен предоставить вам детали самого последнего сообщения, а также его идентификатор потока и имя пользователя.

РЕДАКТИРОВАНИЕ запрос, чтобы выбрать одно последнее сообщение в теме:

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`;
0 голосов
/ 22 июня 2011
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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...