Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Базы Данных > Неоднозначный запрос


Автор: donion 18.2.2011, 21:06
Есть таблица пользовательских логотипов:

Код

---------------
id, user_id, logo
---------------
1,1,22.jpg
2,2,33.jpg
---------------


Есть таблица пользовательских сообщений, друг другу:

Код

--------------
pmid,sender,recipient,text,created,thread
--------------
1,1,2,'hi',1297972942,1
2,2,1,'hello',1297972950,1
--------------


В распоряжение есть user_id, 
С помощью этого user_id нужно запросить из базы последнее сообщение двух людей +
логотип пользователя, который принадлежит оппоненту user_id (т.е. в данном случае если user_id = 1, то пользователю с user_id - 2).

Это вообще возможно сделать одним запросом?
Если да, то хоть какие-то зацепки подскажите, у меня на данный момент получается 3 запроса.




Автор: patap 18.2.2011, 23:04
можешь немного пояснить

у нас есть $user_id, который во второй таблице соответствует sender
нам нужно из второй таблицы достать последнее сообщение, которое отослал sender (т.е. sender = $user_id) и из этой же строки по recipient ид достать logo из таблицы 1 (т.е. в результате логотип должен быть для юзера с ид recipient )

верно ?

Добавлено @ 23:16
ну в общем, если примерно так как я описал, то вот, думаю должно сработать
Код

SELECT users.logo, messages.`text`
FROM users, messages
WHERE messages.sender = $user_id AND messages.recipient = users.user_id
ORDER BY messages.created DESC
LIMIT 1

Автор: donion 18.2.2011, 23:54
Ох, действительно, самого главного не объяснил:
sender и recipient - это айди пользователей, те самые user_id. 

Получается, что поскольку есть только один user_id, то нужно:
- найти все поля где sender(отправитель) или recipient(получатель) являются пользователем (наш user_id);
- сгруппировать по последнему сообщению;
- join'ом запросить логотип, c cоседней таблицы, при этом логотип должен быть не пользователя user_id, а его оппонента.
Ну, это в идеале,а сейчас у меня получаются три запроса, вот они:

Код

SELECT MAX(id) FROM pm WHERE sender = '".$user_id."' OR recipient = '".$user_id."' GROUP BY thread


- так я получил массив айдишек последних диалогов, сохранил их в $ids

Код

SELECT * FROM pm WHERE pmid IN '".$ids."'


- так я получил все последние сообщения, в полном формате (т.е. с текстом и прочей информацией), сохранил в $rows

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

Код

SELECT logo FROM logotypes WHERE user_id ='".$user_id'"


p.s. немного изменил структуру таблиц, в первом сообщении.


Автор: patap 19.2.2011, 00:07
Цитата(donion @  18.2.2011,  22:54 Найти цитируемый пост)
- найти все поля где sender(отправитель) или recipient(получатель) являются пользователем (наш user_id);

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

Цитата(donion @  18.2.2011,  22:54 Найти цитируемый пост)
логотип должен быть не пользователя user_id, а его оппонента.

кто такой оппонет? это есть recipient?

в итоге запрос должен вернуть одно сообщение, последнее?

Автор: donion 19.2.2011, 00:17
Цитата

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


Да, получается, что наш user_id может быть и recipient, и sender. 

Цитата

кто такой оппонет? это есть recipient?


оппонентом может быть и recipient, и sender. 
Приведу пример:
- я написал сообщение другому пользователю, мой айдишник записался в базу как sender, а другого пользователя как recipient;
- и наоборот, кто-то написал мне сообщение, мой айдишник записался в recipient, а id отправителя в sender;

Так вот нужны все записи, где мой айди фигурирует либо в sender, либо в recipient.

Цитата

в итоге запрос должен вернуть одно сообщение, последнее?


В итоге должно вернуть все последние сообщения, в которых фигурировал user_id, при этом лого должен быть оппонента (того, с кем он разговаривал).

Автор: patap 19.2.2011, 09:25
Код

SELECT pm.*, logotypes.* 
FROM pm
INNER JOIN logotypes ON pm.recipient = logotypes.user_id
WHERE pm.recipient = [user_id_here] OR pm.sender = [user_id_here]
ORDER BY pm.created


Цитата(donion @  18.2.2011,  23:17 Найти цитируемый пост)
В итоге должно вернуть все последние сообщения

тут не совсем ясно по какому признаку возвращать последние сообщения. Сейчас возвращает все сообщения, в которых фигурировал юзер с заданным ИД. 
Предполагаю что нужно учитывать created, если да - то добавишь в WHERE нужное условие

Добавлено через 1 минуту и 29 секунд
если я что-то опять не догнал - говори)

Автор: donion 19.2.2011, 13:21
Цитата

тут не совсем ясно по какому признаку возвращать последние сообщения. 


по created или pmid.

Цитата

Сейчас возвращает все сообщения, в которых фигурировал юзер с заданным ИД. 


Да, но логотип все равно будет браться только по recipient, а наш оппонент может быть и sender.

Цитата

Предполагаю что нужно учитывать created, если да - то добавишь в WHERE нужное условие


Да, можно и по created, только WHERE не подойдет, оно выдаст либо последнее сообщение, либо все сообщения, в зависимости от того,
что будет в WHERE условием.

К примеру у нас может быть такая таблица:

Код

--------------
pmid,sender,recipient,text,created,thread
--------------
1,1,2,'hi',1297972942,1
2,2,1,'hello',1297972950,1
3,3,1,'test',1297972951,2
4,4,1,'test2',129797251,3
5,5,1,'test4',129797255,4
6,1,5,'test5',129797256,4
--------------


Если наш user_id =1,
то нам нужны 2,3,4,6 записи. при этом, нужно запросить во второй записи, логотип пользователя 2, в 3 - 3, в 4-4, в 6-5.

т.е. так как нужно в условии, 
Цитата

С помощью этого user_id нужно запросить из базы последнее сообщение двух людей +
логотип пользователя, который принадлежит оппоненту user_id (т.е. в данном случае если user_id = 1, то пользователю с user_id - 2).







Автор: patap 19.2.2011, 16:49
Код

SELECT pm.*, logotypes.* 
FROM pm, logotypes
WHERE (pm.recipient = logotypes.user_id AND pm.sender = [U_ID]) OR (pm.sender = logotypes.user_id AND pm.recipient = [U_ID])
ORDER BY pm.created


как вернуть последнее сообщение...пока нет идей
это, я так понял если к примеру есть следующие данные

Код

1, 1, 2, 'hi',      1297972942, 1
2, 2, 1, 'hello', 1297972950, 1


то нужно вернуть из этих двух сообщений одно, более позднее?

Автор: donion 19.2.2011, 17:14
Цитата

то нужно вернуть из этих двух сообщений одно, более позднее? 


Да, верно.

За запрос - спасибо! Убирает циклические запросы и это замечательно.
Вот бы еще с группировкой что-то решить. 

Автор: Photon 22.2.2011, 23:11
Код

SELECT pm.*, logotypes.* 
FROM pm, logotypes
WHERE (pm.recipient = logotypes.user_id AND pm.sender = [USER_ID]) OR (pm.sender = logotypes.user_id AND pm.recipient = [USER_ID])
ORDER BY pm.created desc limit 1

Автор: patap 24.2.2011, 15:58
Photon, ну это ясно, там в другом причина

Код

pmid   sender  recipient   text                             created          thread
---------------------------------------------------------------------------------------
1            1            2         'mess from 1 to 2'     '2010-01-12'       1
2            2            1         'mess from 2 to 1'     '2010-01-14'       1
3            1            3         'mess from 1 to 3'     '2010-01-03'       1
4            2            1         'mess from 2 to 1'     '2010-01-07'       1
5            4            1         'mess from 4 to 1'     '2010-01-20'       1
6            4            1         'mess from 4 to 1'     '2010-01-11'       1
7            1            3         'mess from 1 to 3'     '2010-01-11'       1


нужно вернуть:
Код

pmid  sender  recipient   text                             created          thread
---------------------------------------------------------------------------------------
2            2            1         'mess from 2 to 1'     '2010-01-14'       1
5            4            1         'mess from 4 to 1'     '2010-01-20'       1
7            1            3         'mess from 1 to 3'     '2010-01-11'       1

Автор: patap 24.2.2011, 17:38
думаю группировать надо по logotypes.user_id

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)