Ci sono molti modi per ottenere ciò che stai chiedendo. Forse il modo più semplice è usare un approccio puramente orientato al set:
select election_id from elections
minus -- except is used instead of minus by some vendors
select election_id from votes where user_id = ?
Dal set di elezioni, rimuoviamo quelli in cui l'utente ha votato. Il risultato può essere unito alle elezioni per ottenere il titolo delle elezioni. Anche se non hai taggato la tua domanda, c'è motivo di credere che stai usando MySQL e MINUS o EXCEPT non sono supportati lì.
Un'altra variante è utilizzare il NOT EXISTS
predicato:
select election_id, title
from elections e
where not exists (
select 1
from votes v
where e.election_id = v.election_id
and v.user_id = ?
);
Cioè le elezioni in cui non esiste un voto da parte dell'utente. Il NOT IN
predicato può essere utilizzato in modo simile. Dal momento che potrebbero esserci nulli, vale la pena notare che la semantica differisce tra IN ed EXISTS.
Infine, è possibile utilizzare un join esterno
select election_id, title
from elections e
left join votes v
on e.election_id = v.election_id
and v.user_id = ?
where v.user_id is null;
Se non ci sono righe che corrispondono al predicato ON, tutte le colonne dei voti vengono sostituite con null nel risultato. Pertanto, possiamo verificare se una colonna dei voti è nulla nella clausola WHERE. Poiché entrambe le colonne nei voti possono essere nulle, devi fare attenzione.
Idealmente, dovresti correggere i tuoi tavoli in modo da non dover affrontare i gotcha causati da null:
CREATE TABLE elections
( election_id int NOT NULL AUTO_INCREMENT PRIMARY KEY
, title varchar(255) not null );
CREATE TABLE votes
( election_id int not null
, user_id int not null
, constraint pk_votes primary key (election_id, user_id)
, constraint fk_elections foreign key (election_id)
references elections (election_id)
);