2013-07-04 2 views
0

Я бы очень признателен за любую помощь, пытающуюся упростить MySQL-запрос. Цель запроса - получить сообщения из таблицы сообщений (users_messages), которая имеет следующие столбцы: message_id, from_id, to_id, message_content, date_sent.Попытка упростить MySQL-запрос

Кому необходимо, чтобы from_id и to_id присоединились к таблице пользователей (пользователей), которая имеет следующие столбцы: user_id, user_username.

Также следует упомянуть, что есть заблокированная таблица пользователей (users_blocked), которая отфильтровывает любые сообщения, если функция user_id в этой таблице.

Все это прекрасно работает, и сообщения упорядочиваются с помощью новейшей первой, которая является тем, что я хочу. Моя единственная проблема заключается в том, что она не тянет соответствующее сообщение message_content. т. е. вытягивает самую последнюю дату, но не последнее сообщение.

Возможно, мне нужен другой подход (например, подзапросы), но я не могу обойти его.

Вот запрос:

select m.message_content, 
    if(from_id < to_id, concat(from_id,to_id), concat(to_id,from_id)) as ft, 
    if (from_id = $my_id, to_id, from_id) as other_id, 
    max(date_sent) as most_recent 
from users_messages m 
    left join users_blocked ub1 on (from_id = ub1.blocked_id and ub1.user_id = $my_id) 
    left join users_blocked ub2 on (to_id = ub2.blocked_id and ub2.user_id = $my_id) 
where 
    (from_id = $my_id or to_id = $my_id) 
    and ub1.blocked_id is null 
    and ub2.blocked_id is null 
group by 
    ft 
order by 
    most_recent desc 

К сожалению, здесь структуры таблиц:

пользователи

user_id user_username 
1   Simon 
2   Amber 
3   Tom

users_messages

 
message_id from_id to_id date_sent    message_content 
1    1   2  2012-07-04 11:52:12 Hello 
2    1   2  2012-07-04 12:32:24 Another message 
3    1   2  2012-07-04 14:00:00 Hello again 

users_blocked

 
user_id blocked_id 
1   3 
+1

Пожалуйста, включите вашу структуру (ы) таблицы. Также - он возвращает 'message_content', но это не правильное значение? Или это ничего не возвращает? – ethrbunny

+3

Это не так уж плохо. Черт, вы можете прочитать все это без прокрутки, что всегда является бонусом! –

+0

не страшно, но я бы, вероятно, просто получил массив заблокированных пользователей и сделал не для for_id – timpone

ответ

0

Try:

select m.message_content, 
     x.ft, 
     x.other_id, 
     x.most_recent 
from (select if(from_id < to_id, concat(from_id,to_id), concat(to_id,from_id)) as ft, 
      if(from_id = $my_id, to_id, from_id) as other_id, 
      max(date_sent) as most_recent 
     from users_messages um 
     left join users_blocked ub1 
     on (um.from_id = ub1.blocked_id and ub1.user_id = $my_id) 
     left join users_blocked ub2 
     on (um.to_id = ub2.blocked_id and ub2.user_id = $my_id) 
     where ub1.blocked_id is null and ub2.blocked_id is null and 
      (um.from_id = $my_id or um.to_id = $my_id) 
     group by ft) x 
join users_messages m 
    on m.date_sent = x.most_recent and 
     m.from_id in ($my_id, x.other_id) and 
     m.to_id in ($my_id, x.other_id) 
order by 
    x.most_recent desc 

SQLFiddle here.

+0

Спасибо, Марк. Я пробовал это, и я получил сообщение об ошибке «Неизвестный столбец« m.from_id »в разделе« where clause ». Я изменил «users_messages» на «users_messages m» в подзапросе, и теперь это возвращает 0 результатов. –

+0

@SimonKing: Я внес некоторые изменения - попробуйте сейчас. –

+0

Пятно на. Абсолютно совершенный. Большое спасибо –

0

Здесь я предполагаю, что SimonKing хочет, содержание сообщения из таблицы users_messages, которая включает в себя следующее условие,

  1. Пользователи не должны заблокированы либо направления,
  2. В самого последние сообщения передаваемых между пользователями

Таким образом, я изменил запрос Марка Баннистера следующим образом:

SELECT temp.* FROM (
SELECT um.*, concat(um.from_id,to_id) as direction FROM userMessages um 
LEFT JOIN userBlocked ub1 ON um.from_id = ub1.user_id AND um.to_id = ub1.blocked_id 
LEFT JOIN userBlocked ub2 ON um.to_id = ub2.user_id AND um.from_id = ub2.blocked_id 
WHERE ub1.user_id is null AND ub1.blocked_id is null AND ub2.user_id is null AND ub2.blocked_id is null 
ORDER BY um.date_sent DESC 
) temp 
GROUP BY direction 

SQL скрипка http://sqlfiddle.com/#!2/bdc77/1/0

+0

Это зависит от наблюдаемого, но недокументированного поведения в MySQL, которое может не работать в будущих версиях; он уже удален из MariaDB (open-source fork MySQL). –

+0

@Mark Bannister, Дайте мне URL-адрес, чтобы получить дополнительную информацию об этом –

+0

Здесь: https://kb.askmonty.org/en/group-by-trick-has-been-optimized-away/ –

0

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

  1. грим набор подготовленных данных, которые будут иметь самые последние даты:

    выберите to_id, from_id, макс (date_sent) как most_recent от users_messages м покинул присоединиться users_blocked иь на ub.user_id = $ my_id и ub.blocked_id в (to_id, from_id) где (from_id = $ my_id или to_id = $ my_id) и ub.blocked_id является нулевым группы по to_id, from_id заказа most_recent убыв

Я вижу вы нащупываете данные двумя столбцами to_id, from_id. Этот подзапрос не лучшее место, чтобы рассчитать такие вещи, как:

if(from_id < to_id, concat(from_id,to_id), concat(to_id,from_id)) as ft 
  1. Затем просто выберите другие необходимые данные из users_messages, что соответствует нашему to_id, from_id и recent_date из подготовленной таблицы:

    выберите гм. * от

    (
    select to_id, from_id, max(date_sent) as most_recent 
    from users_messages m 
    left join users_blocked ub on ub.user_id = 1 
    and ub.blocked_id in (to_id, from_id) 
    where 
    (from_id = 1 or to_id = 1) 
    and ub.blocked_id is null 
    group by 
    to_id, from_id 
    order by 
    most_recent desc 
    ) as prepared_messages 
    left join users_messages um on um.from_id = prepared_messages.from_id 
    and um.to_id = prepared_messages.to_id 
    and um.date_sent = prepared_messages.most_recent 
    
Смежные вопросы