วิธีเข้าร่วมสองตารางเพื่อให้หายไปแถวในตารางที่สอง


21

ในระบบการลงคะแนนแบบง่าย ๆ เช่น

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

สำหรับการรับรายชื่อผู้มีสิทธิเลือกตั้งผู้ใช้ JOIN ต่อไปนี้จะถูกใช้

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

แต่จะได้รับรายชื่อการเลือกตั้งที่ผู้ใช้ไม่ได้ลงคะแนนได้อย่างไร

คำตอบ:


21

ใช้การค้นหาที่มีอยู่ของคุณเพื่อให้ได้ผลลัพธ์ตรงข้ามกับรายการที่คุณต้องการ รายการนั้นสามารถถูกตรวจสอบผ่านทาง NOT IN เพื่อรับรายการที่ต้องการ

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

17

ใช้การเข้าร่วมด้านนอก:

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 จะว่างเปล่าหากไม่มีการลงคะแนนเสียงสำหรับการเลือกตั้งโดยเฉพาะมิฉะนั้นจะปรากฏขึ้น

หากคุณต้องการแสดงรายการการเลือกตั้งโดยที่ไม่มีการลงคะแนนเสียงใด ๆ คุณอาจทำได้ดังนี้:

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

5

มีหลายวิธีในการบรรลุสิ่งที่คุณขอ บางทีวิธีที่ตรงไปตรงมาที่สุดคือการใช้วิธีการที่มุ่งเน้นอย่างหมดจด:

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

จากชุดการเลือกตั้งเราจะลบรายการที่ผู้ใช้โหวต ผลที่ได้สามารถเข้าร่วมกับการเลือกตั้งเพื่อให้ได้ตำแหน่งการเลือกตั้ง แม้ว่าคุณจะไม่ได้ติดแท็กคำถามของคุณ แต่ก็มีเหตุผลที่เชื่อได้ว่าคุณกำลังใช้งาน MySQL และไม่รองรับหรือลบหรือลบออก

อีกตัวแปรหนึ่งคือใช้เพรดิเคต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 คอลัมน์ทั้งหมดจากการลงคะแนนจะถูกแทนที่ด้วยผลลัพธ์ ดังนั้นเราสามารถตรวจสอบว่าคอลัมน์ใด ๆ จากการโหวตเป็นโมฆะในส่วนคำสั่ง WHERE หรือไม่ เนื่องจากทั้งสองคอลัมน์ในการโหวตอาจเป็นโมฆะคุณต้องระวัง

เป็นการดีที่คุณควรแก้ไขตารางของคุณเพื่อให้คุณไม่ต้องจัดการกับ gotchas ที่เกิดจาก nulls:

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

-3
SELECT * 
FROM elections 
WHERE election_id NOT IN (
    SELECT DISTINCT(election_id) from votes
);

4
ในฐานะที่เป็นคำตอบที่ยอมรับดึงการเลือกตั้งที่ผู้มีสิทธิเลือกตั้งที่เฉพาะเจาะจงไม่ได้ลงคะแนนนี้ไม่ได้ตอบคำถามของ OP และแน่นอนว่ามันเป็นเพียงแค่การบิดเล็กน้อยของคำตอบอีกข้อหนึ่งเพื่อรับการเลือกตั้งโดยที่ไม่มีใครโหวต ความคิดเห็นเกี่ยวกับเอฟเฟกต์นั้นอาจทำให้คำตอบดูเหมือนดีขึ้นเล็กน้อย ถึงกระนั้นจากภาพก็ค่อนข้างดีสำหรับลิง! :-)
RDFozz
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.