web-dev-qa-db-ja.com

2つのテーブルを結合して、2番目のテーブルで欠落している行を取得する方法

単純な投票システムでは

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'

しかし、ユーザーが投票していない選挙のリストを取得するにはどうすればよいですか?

23
Googlebot

既存のクエリを使用して、反対のリストを取得します。次に、そのリストを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'
)
22
Sparr

外部結合を使用します。

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
 )
17
druzin

あなたが求めているものを達成する方法はたくさんあります。おそらく最も簡単な方法は、純粋にセット指向のアプローチを使用することです。

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はサポートされていません。

もう1つのバリエーションは、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句でnullかどうかを確認できます。投票の両方の列がnullになる可能性があるため、注意する必要があります。

理想的には、nullが原因の問題に対処する必要がないようにテーブルを修正する必要があります。

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