2012-06-10 2 views
1

Есть ли способ сделать следующий запрос без подзапроса?Улучшить запрос подзапроса

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 = 'непрочитанное'. Оба этих запроса возвращают самый верхний результат ЛЮБОГО потока, который имеет сообщение со статусом = 'непрочитанный'.

То, что я пытаюсь сделать, это нечто вроде любого почтового ящика электронной почты, например Gmail. Предположим, что в папке «Входящие» отображается 25 потоков на первой странице. Я хочу выделить ТОЛЬКО те потоки, которые имеют самое последнее сообщение со статусом = 'непрочитанное' (игнорируя статус любого сообщения, более старого, чем самое последнее).

Вот почему я использую GROUP BY на заказанные результаты, так что я получаю только самый последний результат, и из этих результатов, какой из них имеет статус = «непрочитанные»

(Примечание что я также изменил статус в вышеуказанном запросе от «удалено» до «непрочитанного», чтобы я мог сделать пояснение более понятным.)

+0

Что такое 'thread_id'? Можете ли вы описать таблицу. Пожалуйста. – JHS

+0

@Juniad См. Обновленный вопрос – David542

+0

Что-то не так. Вам не нужно собирать все остальные столбцы не в группе? – wrschneider

ответ

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.

+0

См. Обновление в вопросе, в котором я объясняю запрос, который я ищу. – David542

+0

Хорошо, спасибо за разъяснение в дальнейшем, я понимаю вашу проблему сейчас. См. Мое редактирование. –

+0

Отлично, это работает! Спасибо. – David542

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' 
+0

См. Обновление в вопросе, в котором я объясняю запрос, который я ищу. – David542

Смежные вопросы