Cara GABUNG dua tabel untuk mendapatkan baris yang hilang di tabel kedua

21

Dalam sistem pemungutan suara sederhana seperti

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

untuk mendapatkan daftar pemilihan yang telah dipilih oleh pengguna, GABUNG berikut digunakan

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

tetapi bagaimana cara mendapatkan daftar pemilihan yang belum dipilih oleh pengguna?

Googlebot
sumber

Jawaban:

21

Gunakan kueri Anda yang ada untuk mendapatkan kebalikan dari daftar yang Anda inginkan. Daftar itu kemudian dapat diperiksa melalui NOT IN untuk mendapatkan daftar yang diinginkan.

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
sumber
17

Gunakan gabungan luar:

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

UserId akan kosong jika tidak ada suara yang diberikan untuk pemilihan tertentu, jika tidak maka akan muncul

Jika Anda hanya ingin mendaftar pemilihan di mana tidak ada suara yang diberikan Anda dapat melakukannya seperti ini:

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

Ada banyak cara untuk mencapai apa yang Anda minta. Mungkin cara yang paling mudah adalah dengan menggunakan pendekatan berorientasi murni yang ditetapkan:

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

Dari rangkaian pemilihan, kami menghapus yang telah dipilih oleh pengguna. Hasilnya bisa digabungkan dengan pemilihan untuk mendapatkan judul pemilihan. Meskipun Anda belum menandai pertanyaan Anda, ada alasan untuk percaya bahwa Anda menggunakan MySQL, dan MINUS atau KECUALI tidak didukung di sana.

Varian lain adalah dengan menggunakan NOT EXISTSpredikat:

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

Yaitu pemilihan di mana tidak ada suara dari pengguna. The NOT INpredikat dapat digunakan dengan cara yang sama. Karena mungkin ada nulls yang terlibat, perlu dicatat bahwa semantiknya berbeda antara IN dan EXIS.

Akhirnya, Anda bisa menggunakan gabungan luar

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;

Jika tidak ada baris yang cocok dengan predikat ON, semua kolom dari suara diganti dengan nol pada hasilnya. Karena itu, kami dapat memeriksa apakah kolom dari suara tidak ada dalam klausa WHERE. Karena kedua kolom dalam suara mungkin nol, Anda harus berhati-hati.

Idealnya, Anda harus memperbaiki tabel Anda sehingga Anda tidak harus berurusan dengan gotcha yang disebabkan oleh nol:

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
sumber
-3
SELECT * 
FROM elections 
WHERE election_id NOT IN (
    SELECT DISTINCT(election_id) from votes
);
Dmitriy Grigoryan
sumber
4
Karena jawaban yang diterima menarik pemilihan di mana pemilih tertentu tidak memberikan suara, ini tidak benar-benar menjawab pertanyaan OP. Dan, tentu saja, itu hanya perubahan kecil dari salah satu jawaban lainnya, untuk mendapatkan pemilihan di mana tidak ada yang memilih. Komentar untuk efek itu mungkin membuat ini tampak seperti jawaban yang sedikit lebih baik. Namun, dari gambar, cukup bagus untuk monyet! :-)
RDFozz