Domanda

Sto cercando di costruire una query che includerà una colonna che indica se un utente ha scaricato o meno un documento. Ho una tabella chiamata HasDownload con le seguenti colonne: id, documentID, memberID. Scoprire se un utente ha scaricato un documento specifico è facile; ma devo generare una query in cui i risultati saranno simili a questo:

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

L'ID non è molto importante; ciò che mi interessa è se il documento è stato scaricato (è NULL o no).

Ecco la mia domanda:

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

Il problema è che questo restituirà valori solo se esiste una voce per l'utente specificato nella tabella HasDownloaded. Mi piacerebbe mantenerlo semplice e avere solo voci in HasDownload per i documenti che sono stati scaricati. Quindi, se l'utente 1 ha scaricato abc, bbb e ccc, voglio ancora che ddd ed eee vengano visualizzati nella tabella risultante, solo con l'id come NULL. Ma la clausola WHERE mi dà solo valori per i quali esistono voci.

Non sono un grande esperto di SQL: esiste un operatore che mi darà quello che voglio qui? Dovrei adottare un approccio diverso? O è impossibile?

È stato utile?

Soluzione

Sposta la condizione nella clausola WHERE nella condizione di join.

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

Ciò è necessario ogni volta che si desidera fare riferimento a una tabella di join a sinistra in quella che altrimenti sarebbe la clausola WHERE.

Altri suggerimenti

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

sarebbe il modo normale per farlo. Alcuni lo accorcerebbero a:

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

Puoi, come mostra Matt B., farlo nella tua condizione di JOIN - ma penso che sia molto più probabile che confonda la gente. Se non capisci PERCHÉ spostarlo nella clausola JOIN funziona, ti consiglio vivamente di starne alla larga.

@Mark: capisco perché la sintassi JOIN funziona, ma grazie per l'avvertimento. Penso che il tuo suggerimento sia più intuitivo. Ero curioso di vedere quale fosse più efficiente. Quindi ho eseguito un test rapido (questo era piuttosto semplicistico, temo, su solo 14 file e 10 prove):

Nella condizione JOIN:

AND HasDownloaded.memberID = @memberID
  • Tempo di elaborazione del cliente: 4.6
  • Tempo di esecuzione totale: 35,5
  • Tempo di attesa per le risposte del server: 30.9

Nella clausola WHERE:

WHERE HasDownloaded.memberId IS NULL OR HasDownloaded.memberId = @memberId
  • Tempo di elaborazione del client: 7,7
  • Tempo di esecuzione totale: 27,7
  • Tempo di attesa per le risposte del server: 22.0

Sembra che la clausola WHERE sia sempre così leggermente più efficiente. Interessante! Ancora una volta, grazie ad entrambi per il vostro aiuto.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top