在一个简单的投票系统中,如

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'


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

#1 楼

使用现有查询获取与所需列表相反的列表。然后可以通过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'
)


#2 楼

使用外部联接:

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
 )


#3 楼

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

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


#4 楼

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


评论


由于公认的答案导致了特定选民不参加选举的选举,因此这并不能真正回答OP的问题。当然,这只是对其他答案之一的细微调整,可以使没有人投票的选举得以实现。对此效果发表评论可能会使它看起来似乎是一个更好的答案。尽管如此,从图片上看,对猴子来说还不错! :-)

–RDFozz
17年7月7日在19:25