如何加入两个表以获取第二个表中缺失的行

Goo*_*bot 29 join select

在一个简单的投票系统中

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
Run Code Online (Sandbox Code Playgroud)

为了获取用户投票的选举列表,使用以下 JOIN

SELECT * FROM elections
JOIN votes USING(election_id)
WHERE votes.user_id='x'
Run Code Online (Sandbox Code Playgroud)

但是如何获取用户未投票的选举列表?

Spa*_*arr 29

使用您现有的查询来获取您想要的列表的反面。然后可以通过 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'
)
Run Code Online (Sandbox Code Playgroud)


dru*_*zin 20

使用外连接:

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
Run Code Online (Sandbox Code Playgroud)

如果没有为特定选举投票,则 UserId 将为空,否则会显示

如果您只想列出没有任何投票的选举,您可以这样做:

select *
from elections e
where election_id NOT IN 
 (select election_id
  from votes
  where user_id = @userid
 )
Run Code Online (Sandbox Code Playgroud)


Len*_*art 8

有很多方法可以实现您的要求。也许最直接的方法是使用纯面向集合的方法:

select election_id from elections
minus -- except is used instead of minus by some vendors
select election_id from votes where user_id = ?
Run Code Online (Sandbox Code Playgroud)

从选举集中,我们删除用户投票的选举。结果可以与选举结合以获得选举的标题。即使您没有标记您的问题,也有理由相信您正在使用 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 = ?
);
Run Code Online (Sandbox Code Playgroud)

即不存在用户投票的选举。该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;
Run Code Online (Sandbox Code Playgroud)

如果没有与 ON 谓词匹配的行,则来自 votes 的所有列在结果中都替换为 null。因此,我们可以检查 WHERE 子句中来自 votes 的任何列是否为空。由于投票中的两列都可能为空,因此您需要小心。

理想情况下,您应该修复您的表,以便您不必处理由空值引起的问题:

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)
);   
Run Code Online (Sandbox Code Playgroud)