Існує маса способів досягти того, про що ви просите. Мабуть, найпростіший спосіб - це використовувати суто орієнтований підхід:
select election_id from elections
minus -- except is used instead of minus by some vendors
select election_id from votes where user_id = ?
З набору виборів ми видаляємо ті, де користувач проголосував. Результат можна приєднати до виборів, щоб отримати назву виборів. Незважаючи на те, що ви не позначили своє питання, є підстави вважати, що ви використовуєте MySQL, а MINUS або EXCEPT там не підтримуються.
Іншим варіантом є використання NOT EXISTS
присудка:
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 = ?
);
Тобто вибори там, де не існує голосування від користувача. NOT IN
Предикат може бути використаний аналогічним чином. Оскільки можуть бути задіяні нулі, варто відзначити, що семантика відрізняється між IN та EXISTS.
Нарешті, ви можете використовувати зовнішнє з'єднання
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;
Якщо немає рядків, що відповідають предикату ON, усі стовпці з голосів замінюються на null в результаті. Таким чином, ми можемо перевірити, чи будь-який стовпчик з голосів недійсний у пункті WHERE. Оскільки обидва стовпці голосів можуть бути недійсними, вам потрібно бути обережними.
В ідеалі вам слід виправити свої таблиці, щоб вам не доводилося мати справу з отриманими нулями:
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)
);