トップページに戻る    次のSQLパズルへ    前のSQLパズルへ

9-22 存在有無のブール値で論理演算

SQLパズル

CandidateSkillsテーブル
candidateID  skill_code
-----------  -------------
        100  accounting
        100  inventory
        100  manufacturing
        200  accounting
        200  inventory
        300  manufacturing
        400  inventory
        400  manufacturing
        500  accounting
        500  manufacturing

candidateIDごとに、
skill_code=manufacturing のレコードが存在し、
かつ
skill_code=inventory または skill_code=accounting のレコードが存在する
candidateIDの全レコードを出力する。

出力結果
candidateID  skill_code
-----------  -------------
        100  accounting
        100  inventory
        100  manufacturing
        400  inventory
        400  manufacturing
        500  accounting
        500  manufacturing

SQLパズル(日本語版)のパズル16 [職業斡旋] を参考にさせていただきました
SQLパズル 第2版のパズル17 [人材紹介会社] を参考にさせていただきました


データ作成スクリプト

create table CandidateSkills(
candidateID integer,
skill_code  text,
primary key(candidateid,skill_code));

insert into CandidateSkills values(100,'accounting');
insert into CandidateSkills values(100,'inventory');
insert into CandidateSkills values(100,'manufacturing');
insert into CandidateSkills values(200,'accounting');
insert into CandidateSkills values(200,'inventory');
insert into CandidateSkills values(300,'manufacturing');
insert into CandidateSkills values(400,'inventory');
insert into CandidateSkills values(400,'manufacturing');
insert into CandidateSkills values(500,'accounting');
insert into CandidateSkills values(500,'manufacturing');


SQL

--■■■window関数を使う方法■■■
select candidateID,skill_code
from (select candidateID,skill_code,
          bool_or(skill_code='manufacturing') over(partition by candidateID)
      and bool_or(skill_code in('inventory','accounting')) over(partition by candidateID)
       as willOut
        from CandidateSkills) a
 where willOut
order by candidateID,skill_code;

--■■■window関数を使わない方法1■■■
select candidateID,skill_code
  from CandidateSkills a
 where exists(select 1 from CandidateSkills b
               where b.candidateID = a.candidateID
              having bool_or(b.skill_code='manufacturing')
                 and bool_or(b.skill_code in('inventory','accounting')))
order by candidateID,skill_code;

--■■■window関数を使わない方法2■■■
select candidateID,skill_code
  from CandidateSkills a
 where exists(select 1 from CandidateSkills b
               where b.candidateID = a.candidateID
                 and b.skill_code in('manufacturing','inventory','accounting')
              having bool_or(b.skill_code='manufacturing')
                 and bool_or(b.skill_code in('inventory','accounting')))
order by candidateID,skill_code;


解説

PostgreSQLは、select文やテーブル値としても、boolean型をサポートします。
また、8.4からは、存在肯定命題の集合関数であるbool_or関数がwindow関数として使えます。

9.18. 集約関数

OracleSQLパズル 9-22 存在有無のブール値で論理演算