So verbinden Sie zwei Tabellen, um fehlende Zeilen in der zweiten Tabelle zu erhalten

21

In einem einfachen Abstimmungssystem als

CREATE TABLE elections (
election_id int(11) NOT NULL AUTO_INCREMENT,
title varchar(255),

CREATE TABLE votes (
election_id int(11),
user_id int(11),
FOREIGN KEYs

Um die Liste der Wahlen zu erhalten, die ein Benutzer gewählt hat, wird der folgende JOIN verwendet

SELECT * FROM elections
JOIN votes USING(election_id)
WHERE votes.user_id='x'

aber wie bekomme ich die Liste der Wahlen, die ein Benutzer NICHT gewählt hat?

Googlebot
quelle

Antworten:

21

Verwenden Sie Ihre vorhandene Abfrage, um das Gegenteil der gewünschten Liste zu erhalten. Diese Liste kann dann mit NOT IN verglichen werden, um die gewünschte Liste zu erhalten.

SELECT * FROM elections WHERE election_id NOT IN (
    SELECT elections.election_id from elections
    JOIN votes USING(election_id)
    WHERE votes.user_id='x'
)
Sparr
quelle
17

Verwenden Sie eine äußere Verknüpfung:

select e.election_id, e.title, v.user_id
from Elections e
 LEFT OUTER JOIN votes v ON v.election_id = e.election_id and v.user_id = @userid

Die Benutzer-ID ist leer, wenn für eine bestimmte Wahl keine Stimmen abgegeben wurden. Andernfalls wird sie angezeigt

Wenn Sie nur die Wahlen auflisten möchten, bei denen es keine abgegebenen Stimmen gibt, können Sie dies folgendermaßen tun:

select *
from elections e
where election_id NOT IN 
 (select election_id
  from votes
  where user_id = @userid
 )
Druzin
quelle
5

Es gibt viele Möglichkeiten, um das zu erreichen, wonach Sie fragen. Am einfachsten ist es vielleicht, einen rein satzorientierten Ansatz zu verwenden:

select election_id from elections
minus -- except is used instead of minus by some vendors
select election_id from votes where user_id = ?

Aus der Reihe der Wahlen entfernen wir diejenigen, bei denen der Benutzer abgestimmt hat. Das Ergebnis kann mit Wahlen verbunden werden, um den Titel der Wahlen zu erhalten. Auch wenn Sie Ihre Frage nicht mit Tags versehen haben, besteht Grund zu der Annahme, dass Sie MySQL verwenden und MINUS oder EXCEPT dort nicht unterstützt werden.

Eine andere Variante besteht darin, das NOT EXISTSPrädikat zu verwenden:

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 = ?
);

Dh bei der Wahl, bei der es keine Abstimmung vom Nutzer gibt. Das NOT INPrädikat kann auf ähnliche Weise verwendet werden. Da es sich möglicherweise um Nullen handelt, ist zu beachten, dass sich die Semantik zwischen IN und EXISTS unterscheidet.

Schließlich können Sie eine äußere Verknüpfung verwenden

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;

Wenn es keine Zeilen gibt, die mit den ON-Prädikaten übereinstimmen, werden alle Spalten von votes im Ergebnis durch null ersetzt. Wir können daher überprüfen, ob eine Spalte von Stimmen in der WHERE-Klausel null ist. Da beide Spalten in Stimmen möglicherweise null sind, müssen Sie vorsichtig sein.

Idealerweise sollten Sie Ihre Tabellen so korrigieren, dass Sie sich nicht mit den durch Nullen verursachten Fallstricken befassen müssen:

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)
);   
Lennart
quelle
-3
SELECT * 
FROM elections 
WHERE election_id NOT IN (
    SELECT DISTINCT(election_id) from votes
);
Dmitriy Grigoryan
quelle
4
Da die akzeptierte Antwort Wahlen ergab, bei denen ein bestimmter Wähler nicht gewählt hat, ist die Frage des OP damit nicht wirklich beantwortet. Und natürlich ist es nur eine kleine Änderung einer der anderen Antworten, Wahlen abzuhalten, bei denen niemand gewählt hat. Ein Kommentar zu diesem Effekt könnte dies wie eine etwas bessere Antwort erscheinen lassen. Trotzdem, vom Bild her ziemlich gut für einen Affen! :-)
RDFozz