2010-04-17 6 views
1

ma requête:mysql résultat de filtrage à l'aide rejoindre externe gauche

 SELECT content.*, activity_log.content_id FROM content 
     LEFT JOIN activity_log 
     ON content.id = activity_log.content_id 
     AND sess_id = '$sess_id' 
     WHERE activity_log.content_id IS NULL 
     AND visibility = $visibility 
     AND content.reported < ".REPORTED_LIMIT." 
     AND content.file_ready = 1 
     LIMIT 1 

Le but de cette requête est d'obtenir 1 ligne de la table de contenu qui n'a pas été vu par l'utilisateur (identifié par session_id), mais renvoie toujours le contenu qui a été consulté. Qu'est-ce qui ne va pas? (J'ai vérifié la table en vous assurant que les content_ids sont là)

Note: Je pense que cela est plus efficace que d'utiliser des sous-requêtes pensées?

+0

Oui, MySQL (atleast 5.0 et ci-dessous), cela est plus efficace que d'utiliser les sous-requêtes. Je ne vois pas pourquoi la requête ne fonctionne pas bien. – Wolph

+0

Quel est le point de retour 'activity_log.content_id' dans le SELECT lorsque vous avez dit dans la clause WHERE qu'il doit être NULL? –

+0

Si 'activity_log.content_id' est nul? – Thomas

Répondre

1

Le problème est évidemment dans votre condition join. L'optimisation que vous utilisez (l'application d'une condition à la table de base) est logique lorsque vous êtes intéressé par jointure interne des résultats, mais dans le cas d'un OUTER JOIN cela est lu comme suit: trouver des correspondances entre content et activity_log lignes lorsque les matches id contenu et les matches de l'identifiant de session et le retour des valeurs NULL activity_log lignes lorsque les journaux soit pour l'identifiant de contenu est manquant, ou l'identifiant contenu ne manque pas, mais l'identifiant de session n'est pas celle spécifiée. Et c'est à peine ce que tu veux.

Votre requête devrait devrait ressembler à ceci:

SELECT content.*, activity_log.content_id 
FROM (
SELECT * 
FROM content 
WHERE sess_id = '$sess_id' 
    AND visibility = $visibility 
    AND file_ready = 1 
    AND reported < ".REPORTED_LIMIT." 
) as content 
LEFT JOIN activity_log 
ON content.id = activity_log.content_id 
WHERE activity_log.content_id IS NULL 
LIMIT 1; 

Si les performances ne sont pas optimales, vous pouvez envisager de créer un indice composite sur (sess_id, visibilité, fileready, a rapporté).

Questions connexes