MySQL: запрос на 3 таблицы соединения? - PullRequest
0 голосов
/ 07 декабря 2009

У меня есть три таблицы (пользователь, друзья, сообщения) и два пользователя (пользователь1 и пользователь2).

Когда user1 добавляет пользователя user2 в друзья, user1 может видеть сообщения пользователя user2, как на Facebook. Но только сообщения после даты, когда user1 добавил user2 в друзья. Мой запрос таков:

$sql = mysql_query("SELECT * FROM posts p JOIN friends f ON 
        p.currentuserid = f.friendid AND p.time >= f.friend_since OR 
        p.currentuserid='user1id' WHERE f.myid='user1id' 
        ORDER BY p.postid DESC LIMIT 20");

все работает нормально, но с небольшой проблемой ..... !! он отображает сообщения user2, user3 (все пользователи как друзья пользователя user1) за один раз, но несколько записей user1 ....... т.е.

user2. hi
user1. userssfsfsfsfsdf
user1. userssfsfsfsfsdf
user3. dddddddd
user1. sdfsdsdfsdsfsf
user1. sdfsdsdfsdsfsf

но я в базе данных это одна запись / сообщение, почему это происходит ........ !!

Как я могу это исправить?

Ответы [ 4 ]

0 голосов
/ 24 мая 2014

Вы действительно должны дать некоторое представление о том, как выглядит схема, чтобы нам не приходилось делать так много предположений. Я предполагаю, что первичный ключ user равен id, а friends имеет поле userid, а также поле friendid. Я также предполагаю, что posts.currentuserid - это идентификатор пользователя, который создал сообщение. Если нет, замените его на posts.userid или на любое другое правильное поле.

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

SELECT p.*
FROM user u
JOIN friends f ON u.id = f.userid
JOIN posts p ON ((u.id = p.currentuserid) OR (f.friendid = p.currentuserid AND p.time >= f.friend_since))
WHERE u.id = ?
ORDER BY p.postid DESC LIMIT 20

Второе соединение - это место, где мясо. В нем указано, что для того, чтобы прочитать сообщение, оно (а) должно быть написано вами или (б) написано вашим другом ПОСЛЕ того, как вы подружились с ним.

Если вы также хотите получить имя пользователя, который создал пост (при условии, что user.name содержит имя пользователя), вам нужно 3-е объединение:

SELECT pu.name as 'Posted By', p.*
FROM user u
JOIN friends f ON u.id = f.userid
JOIN posts p ON ((u.id = p.currentuserid) OR (f.friendid = p.currentuserid AND p.time >= f.friend_since))
JOIN user pu ON p.currentuserid = pu.id
WHERE u.id = ?
ORDER BY p.postid DESC LIMIT 20
0 голосов
/ 07 декабря 2009

Я думаю, что самое простое решение - использовать оператор GROUP BY для столбца posts.userId для удаления повторяющихся записей. Однако это не оптимизированный способ решения проблемы.

0 голосов
/ 08 января 2010

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

Добавьте туда f.friendid = 'user2id' (или любое другое имя столбца) перед предложением WHERE.

0 голосов
/ 07 декабря 2009

Я не эксперт по SQL, но я думаю, что ваша проблема в состоянии JOIN. Я не могу понять, как вы можете присоединиться к сообщениям и друзьям и получить результат, который вам нужен. Эксперт по SQL может знать это, но для меня это слишком сложно.

На вашем месте я бы разбил проблему на 2 части:

  1. Выберите собственные сообщения пользователя

  2. Выберите сообщения друга пользователя

Например, вы можете сделать это, используя 2 различных условия и выполнить объединение с таблицей друзей в подзапросе (я не проверял это!):

select * 

from posts p

where 

p.currentuserid = 'user1id'

or 

p.postid in 

(
select p2.postid
from posts p2 
join friend f on p2.currentuserid = f.friendid 
where p2.time >= f.friend_since and f.myid='user1id' 
)

Другой способ сделать это - использовать объединение (также не проверенное ..):

select * 

from posts p

where 

p.currentuserid = 'user1id'

union 

select p2.*

from posts p2 

join friend f on p2.currentuserid = f.friendid 

where p2.time >= f.friend_since and f.myid='user1id' 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...