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


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を使用していると信じる理由があり、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述語は、同様の方法で使用することができます。nullが含まれている可能性があるため、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によって引き起こされる落とし穴に対処する必要がないように、テーブルを修正する必要があります。

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の質問に答えません。そして、もちろん、誰も投票していない選挙をするための、他の答えの1つを少し調整しただけです。その効果に対するコメントは、これを少し良い答えのように思わせるかもしれません。それでも、写真から、サルにはかなり良いです!:
RDFozz
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.