Question

J'essaie de créer une requête qui inclura une colonne indiquant si un utilisateur a téléchargé un document ou non. J'ai une table appelée HasDownloaded avec les colonnes suivantes: id, documentID, memberID. Il est facile de savoir si un utilisateur a téléchargé un document spécifique . mais je dois générer une requête dont les résultats ressemblent à ceci:

name              id
----------------------
abc               NULL
bbb               2
ccc               53
ddd               NULL
eee               13

L'identifiant n'est pas vraiment important; Ce qui m'intéresse, c'est de savoir si le document a été téléchargé (est-il nul ou non).

Voici ma requête:

SELECT Documents.name, HasDownloaded.id FROM Documents
LEFT JOIN HasDownloaded ON HasDownloaded.documentID = Documents.id
WHERE HasDownloaded.memberID = @memberID

Le problème est que cela ne retournera des valeurs que s'il existe une entrée pour l'utilisateur spécifié dans la table HasDownloaded. J'aimerais que cela reste simple et que seules les entrées HasDownloaded soient entrées pour les documents ayant été téléchargés . Donc, si l'utilisateur 1 a téléchargé abc, bbb et ccc, je veux toujours que ddd et eee apparaissent dans la table résultante, avec simplement l'id en tant que NULL. Mais la clause WHERE ne me donne que les valeurs pour lesquelles des entrées existent.

Je ne suis pas vraiment un expert en SQL - existe-t-il un opérateur qui me donnera ce que je veux ici? Devrais-je adopter une approche différente? Ou est-ce impossible?

Était-ce utile?

La solution

Déplacez la condition de la clause WHERE vers la condition de jointure.

SELECT Documents.name, HasDownloaded.id FROM Documents
LEFT JOIN HasDownloaded ON HasDownloaded.documentID = Documents.id 
  AND HasDownloaded.memberID = @memberID 

Cela est nécessaire chaque fois que vous souhaitez faire référence à une table jointe de gauche dans ce qui serait autrement la clause WHERE.

Autres conseils

WHERE HasDownloaded.memberId IS NULL OR HasDownloaded.memberId = @memberId

serait la manière normale de le faire. Certains voudraient le raccourcir à:

WHERE COALESCE(HasDownloaded.memberId, @memberId) = @memberId

Vous pouvez, comme le montre Matt B., le faire dans votre condition JOIN - mais je pense que cela est beaucoup plus susceptible de confondre les gens. Si vous ne comprenez pas pourquoi le passage à la clause JOIN fonctionne, alors je vous suggère fortement de vous en éloigner.

@Mark: Je comprends pourquoi la syntaxe JOIN fonctionne, mais merci pour l'avertissement. Je pense que votre suggestion est plus intuitive. J'étais curieux de voir lequel était le plus efficace. Alors j’ai fait un test rapide (c’était plutôt simpliste, je pense, sur seulement 14 lignes et 10 essais):

Dans la condition JOIN:

AND HasDownloaded.memberID = @memberID
  • Temps de traitement du client: 4.6
  • Durée totale d'exécution: 35.5
  • Temps d'attente pour les réponses du serveur: 30.9

Dans la clause WHERE:

WHERE HasDownloaded.memberId IS NULL OR HasDownloaded.memberId = @memberId
  • Temps de traitement du client: 7.7
  • Durée totale d'exécution: 27,7
  • Temps d'attente pour les réponses du serveur: 22.0

Il semble que la clause WHERE soit légèrement plus efficace. Intéressant! Encore une fois, merci à vous deux pour votre aide.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top