# 問合せ

問合せにより、既存表や表に組込みの定数を基にして、仮想的な表が作られます。

#### Syntax

    {
        ( Query ) |
        Query INTERSECT [ ALL | DISTINCT ] Query |
        Query EXCEPT [ ALL | DISTINCT ] Query |
        Query UNION [ ALL | DISTINCT ] Query |
        選択式 | VALUES式
    }

問合せの前後に任意で括弧を置くことができます。また、INTERSECT、EXCEPT、UNION演算子の評価順を括弧を使って変えることができます。INTERSECTを除きこれらの演算子は、括弧がなければ左から右に評価されます。INTERSECTはUNIONあるいはEXCEPTより前に評価されます。

#### UNION、INTERSECT、EXCEPT ALLにおける結果の重複

ALLとDISTINCTというキーワードにより処理結果から重複を取り除くか否かが決まります。 DISTINCTというキーワードがあれば、結果に重複行はありません。ALLというキーワードがあれば、入力によって結果に重複行がある場合があります。既定はDISTINCTなので、ALLかDISTINCTか指定しなければ重複は取り除かれます。例えばUNIONの場合は、両方の問合せの全行を元に一時的なResultSetを生成したのち、重複行を取り除いてから結果を返します。これがUNION ALLならば、両方の問合せの全行が返されます。

左表にある重複した行の数をL、右表にある左表と同じ内容で重複した行の数をRとすると、どの操作を行うかにより、結果表にある重複した行の数は次のようにきまります。(ALLが指定されたとします。)

- UNION: ( L + R )。
- EXCEPT: ( L – R )と0(零)のうち大きいほう
- INTERSECT: LとRのうち小さいほう

#### 例

    -- 選択式
    SELECT *
    FROM ORG

    -- 副問合せ
    SELECT *
    FROM (SELECT CLASS_CODE FROM CL_SCHED) AS CS

    -- 副問合せ
    SELECT *
    FROM (SELECT CLASS_CODE FROM CL_SCHED) AS CS (CLASS_CODE)

    -- UNIONにより
    -- ORGという表にある全行の
    -- DEPTNUMBとMANAGERという列に加え、
    -- (1,2)と(3,4)を返す。
    -- なお、DEPTNUMBとMANAGERはsmallint型の列である。
    SELECT DEPTNUMB, MANAGER
    FROM ORG
    UNION ALL
    VALUES (1,2), (3,4)

    -- 値の式
    VALUES (1,2,3)

    -- EMPLOYEEという表にて部署番号(WORKDEPT)が'E'で始まる社員および、
    -- EMP_ACTという表にてプロジェクト番号(PROJNO)が
    -- 'MA2100'、'MA2110'あるいは'MA2112'のプロジェクトにアサインされている社員の
    -- 社員番号(EMPNO)を一覧する。
    SELECT EMPNO
         FROM EMPLOYEE
         WHERE WORKDEPT LIKE 'E%'
      UNION
      SELECT EMPNO
         FROM EMP_ACT
         WHERE PROJNO IN('MA2100', 'MA2110', 'MA2112')
    -- 前の例と同じ内容の問合せを行い、EMPLOYEEという表から得た行には'emp'、
    -- EMP_ACTという表から得た行には'emp_act'という"タグ"をつける。
    -- どちらの表から来たかをあらわす"タグ"があるので、
    -- この問合せは前の問合せとは違い、同じEMPNOを一回より多く返すことがある。
    SELECT EMPNO, 'emp'
         FROM EMPLOYEE
         WHERE WORKDEPT LIKE 'E%'
      UNION
      SELECT EMPNO, 'emp_act' FROM EMP_ACT
         WHERE PROJNO IN('MA2100', 'MA2110', 'MA2112')
    -- 前の例とほぼ同じ内容の問合せである。
    -- UNION ALLが指定されたので重複は取り除かれなくなる。
    SELECT EMPNO
          FROM EMPLOYEE
          WHERE WORKDEPT LIKE 'E%'
      UNION ALL
      SELECT EMPNO
         FROM EMP_ACT
         WHERE PROJNO IN('MA2100', 'MA2110', 'MA2112')
    -- 前の例とほぼ同じ内容の問合せである。
    -- いずれの表にもいない二人の社員を加えて、
    -- その行に"new"というタグをつけた。
     SELECT EMPNO, 'emp'
         FROM EMPLOYEE
         WHERE WORKDEPT LIKE 'E%'
      UNION
      SELECT EMPNO, 'emp_act'
         FROM EMP_ACT
         WHERE PROJNO IN('MA2100', 'MA2110', 'MA2112')
      UNION
         VALUES ('NEWAAA', 'new'), ('NEWBBB', 'new')

Parent topic: SQL 問い合わせ