2014-06-27 1 views
1

J'ai 4 tables: posts, users, mentions, followingObtenez des enregistrements uniques basés sur plusieurs se joindre à conditionals

posts 
---------------------------- 
id | user_id | post_text 
1  1   foo 
2  1   bar 
3  2   hello 
4  3   jason 

users 
------------ 
id | name 
1  jason 
2  nicole 
3  frank 

mentions 
-------------------------- 
id | post_id | user_id 
1  4   1 


following 
------------------------------------------------- 
id | user_id | user_id_of_user_being_followed 
1  1   2 

posts inclut le user_id de l'utilisateur qui a posté un texte users a l'ID utilisateur et nom de l'utilisateur mentions a l'ID de poste et l'ID de tout message ayant mentionné 1 ou plusieurs autres utilisateurs following a l'identifiant de l'utilisateur et l'utilisateur qu'ils suivent (l'utilisateur peut suivre de 0 à nombreux utilisateurs)

Ce que j'essaye de faire est de renvoyer tous les messages des utilisateurs qu'un utilisateur donné suit, PLUS tous les messages qui ont mentionné cet utilisateur (si l'utilisateur donné suit), sans retourner les doublons.

SELECT p.id, p.post, u.name, 
FROM following f 
JOIN posts p ON f.following = p.user_id 
JOIN users u ON u.id = p.user_id 
WHERE f.user_id = :user; 

Les rendements supérieurs à tous les messages des utilisateurs qu'un utilisateur donné est ce qui suit, mais je me bats à trouver comment inclure mentionne aussi (rappelez-vous, un utilisateur ne doit pas suivre quelqu'un pour être en mesure de voir le poste dont ils ont été mentionnés).

MISE À JOUR: Merci à John RI a pu comprendre cela:

SELECT DISTINCT(p.id), p.post, u.name 
FROM posts p 
LEFT JOIN following f ON f.following = p.user_id 
LEFT JOIN mentions m ON m.posts_id = p.id 
JOIN users u ON u.id = p.user_id 
WHERE (f.user_id = :user_id OR m.user_id = :user_id) 

Répondre

1

si je comprends votre querstion correctement vous ne voudriez une jointure gauche pour inclure toutes les mentions .. mais pas filtrer les disciples/des postes

si vous pouvez ajouter quelques exemples de données jouer avec je peux vous assurer que son travail la façon dont vous voulez qu'il ...

SELECT 
    if(p.id is not null, p.id, p1.id) as post_id, 
    if(p.post is not null, p.post, p1.post) as post_text, 
    u.username, m.id, m.user_id 
FROM posts p 
JOIN users u on u.id = p.user_id 
JOIN following f on f.user_id_of_user_being_followed = u.id 
LEFT JOIN mentions m on m.user_id = f.user_id 
LEFT JOIN posts p1 on p1.id = m.post_id 
WHERE f.user_id = :user or m.user_id = :user; 

J'ai quitté les mentions jointes à la publication et aussi lorsque l'id_utilisateur dans la table de mention est égal à l'utilisateur spécifié pour filtrer les autres utilisateurs. la jointure gauche ne devrait pas modifier le nombre de lignes retournées .. mais comprennent toutes les mentions


EDIT:WORKING FIDDLE

après avoir joué avec elle, je compris qu'il essayait de mettre tous les données en une ligne .. essayez ceci:

(
    SELECT p.id, p.post_text, u.name 
    FROM posts p 
    JOIN users u on u.id = p.user_id 
    JOIN following f on f.user_id_of_user_being_followed = u.id 
    WHERE f.user_id = 1 
) 
UNION 
(
    SELECT p.id, p.post_text, u.name 
    FROM following f 
    JOIN mentions m on m.user_id = f.user_id 
    JOIN posts p on p.id = m.post_id 
    join users u on u.id = p.user_id 
    WHERE f.user_id = 1 
); 
+0

hmm, cela ne semble pas fonctionner parce que nous avons déjà limité les messages renvoyés en fonction de 'JOIN JOINs p ON f.following = p.user_id' - du moins je pense que c'est la raison pour laquelle. – kylex

+0

pouvez-vous fournir quelques lignes de données pour que je puisse travailler avec? je peux voir où je manque en théorie si vous faites –

+0

modifié le message original. comme vous pouvez le voir, l'utilisateur 1 est seulement l'utilisateur 2 suivant, cependant l'utilisateur 3 a mentionné l'utilisateur 1 dans la publication 4. Ainsi l'utilisateur 1 devrait voir tous les messages de l'utilisateur 2, ET le poste dans lequel ils ont été mentionnés table). – kylex

-1

Peut-être que vous avez hérité de ce DB; mais la dernière table n'est pas vraiment en ligne avec une bonne normalisation des données. La table doit être l'id et le following_id; comme configuré, vous finirez par manquer de colonnes (ou devez continuer à les ajouter quand un utilisateur reçoit une erreur) - les nouveaux utilisateurs ne pourront suivre personne.

Questions connexes