• 締切済み
  • すぐに回答を!

SQLの問題で解答を見ても腑に落ちません

問題集の答えが腑に落ちないのでどなたかわかりやすく説明いただけますでしょうか? EMP表 EMPNO ENAME  SAL   MGR  DEPTNO -------------------------------------- 1000  SCOTT  1000  NULL  10 1010  ADAMS  2000  1000  10 1030  TAYLOR  600   1000  30 1050  MILLER  800   1030  10 以下の副問い合わせを使ったSELECT文を実行した。検索されるデータ件数を選びなさい。 select empno,ename from emp where empno not in (select mgr from emp); A:0件 B:1件 C:2件 D:3件 解答はAの0件なのですが、なぜ0件なのでしょうか? 当方の解釈ですと、副問い合わせでmgrが(NULL,1000,1030)となり where empno not in (NULL,1000,1030) で 「empnoがNULLでも1000でも1030でもない件数」 となり、empnoが1010と1050の行が検索され、cの2件が正解なのでは? と思っているのですが・・・ 間違いをわかりやすく教えていただけますでしょうか? 宜しくお願いします。

共感・応援の気持ちを伝えよう!

  • 回答数4
  • 閲覧数211
  • ありがとう数3

みんなの回答

  • 回答No.4

他の解答者さんもおっしゃっているように、論理演算子「AND」の問題ですね。(質問者さんは、どうやら比較演算子「NOT IN」の方は理解されているようですし。) >nullが検索されるとなぜ0件なのか教えていただけますでしょうか。 通常は、0『偽(FALSE)』か1『真(TRUE)』 のどちらかなのですが、NULLがきた場合、AND演算子では検索の処理を強制終了したような感じとなって「0件」、つまり該当する件数無しとする訳ですね。 where empno <> NULL  AND empno <> 1000  AND empno <> 1030 は、0です。

参考URL:
http://www.rfs.jp/sb/sql/02/02.html#AND

共感・感謝の気持ちを伝えよう!

関連するQ&A

  • エラー「無効な識別子です」

    ORA-00904: "EMPNO": 無効な識別子です と表示されます。 解決方法知っている方、教えていただければ幸いです。 SELECT EMPNO, ENAME, D.DEPTNO, DNAME FROM DEPT D WHERE EMPNO = (SELECT EMPNO FROM EMP WHERE MGR IS NULL) SQL> DESCRIBE EMP; 名前 NULL? 型 ----------------------------------------- -------- ---------------------------- EMPNO NOT NULL NUMBER(4) ENAME VARCHAR2(10) JOB VARCHAR2(9) MGR NUMBER(4) HIREDATE DATE SAL NUMBER(7,2) COMM NUMBER(7,2) DEPTNO NOT NULL NUMBER(2)

  • エラー「単一グループのグループ関数ではありません」

    エラーをどうやれば修正できるかわかりません。 回答のほどよろしくお願いいたします。 SELECT EMPNO, ENAME, DEPTNO, SAL FROM EMP HAVING AVG(SAL) >ANY (SELECT SAL FROM EMP WHERE HIREDATE LIKE '82%') SQL> DESCRIBE EMP; 名前 NULL? 型 ----------------------------------------- -------- ---------------------------- EMPNO NOT NULL NUMBER(4) ENAME VARCHAR2(10) JOB VARCHAR2(9) MGR NUMBER(4) HIREDATE DATE SAL NUMBER(7,2) COMM NUMBER(7,2) DEPTNO NOT NULL NUMBER(2)

  • 自己結合について

    下記SQL文のSELECT句、m.empnoによって左項DEPTNOのMGR値がきちんと出力される理屈がよく分かりません。 回答のほどよろしくお願い致します。 select e.empno, m.empno from emp e join emp m on(e.mgr = m.empno) EMPNO EMPNO ---------- ---------- 7698 7839 7782 7839 7566 7839 7902 7566 7369 7902 7499 7698 7521 7698 7654 7698 7788 7566 7844 7698 7876 7788 7900 7698 7934 7782 13行が選択されました。 SQL> describe emp; 名前 NULL? 型 ------------------------------ EMPNO  NOT NULL NUMBER(4) ENAME      VARCHAR2(10) JOB VARCHAR2(9) MGR NUMBER(4) HIREDATE DATE SAL NUMBER(7,2) COMM NUMBER(7,2) DEPTNO   NOT NULL NUMBER(2)

  • 回答No.3
  • 3rd_001
  • ベストアンサー率66% (115/174)

こういうときはマニュアルを参照しましょう。以下に解説されております。マニュアルどおりの動きですよ。 http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/server.102/B19201-02/conditions.html#10694 >NOT IN演算子に続くリストの中のいずれかの項目がNULLの場合は、すべての行はFALSEまたは不明(UNKNOWN)と評価されます(行は戻されません)。 >たとえば、次の文ではそれぞれの行に対して文字列'True'が戻されます。 > >SELECT 'True' FROM employees > WHERE department_id NOT IN (10, 20); > >ただし、次の文では行は戻されません。 > >SELECT 'True' FROM employees > WHERE department_id NOT IN (10, 20, NULL); > >この例で行が戻されないのは、WHERE句の条件が次のように評価されるためです。 > >department_id != 10 AND department_id != 20 AND department_id != null > >3番目の条件でdepartment_idとNULLの比較が行われるため、この条件の結果がUNKNOWNとなり、 >式全体の結果がFALSE(department_idを持つ行が10または20と等しいため)となります。 >特に、NOT IN演算子が副問合せを参照するときは、 >このような動作を見逃してしまう可能性があることに注意してください。 > >また、NOT IN条件が、行を戻さない副問合せを参照する場合は、 >次のように、すべての行が戻されます。 > >SELECT 'True' FROM employees > WHERE department_id NOT IN (SELECT 0 FROM DUAL WHERE 1=2);

共感・感謝の気持ちを伝えよう!

  • 回答No.2
  • dda167
  • ベストアンサー率76% (55/72)

NOT INの罠ですね。 以下のページが参考になるでしょう。 3値論理とNULL(http://codezine.jp/article/detail/532?p=1

共感・感謝の気持ちを伝えよう!

  • 回答No.1

意地悪な引っ掛け問題に、見事に引っかかってる感じだな。 select empno,ename from emp where empno not in (select mgr from emp); は、0件。 select empno,ename from emp where empno not in (select mgr from emp where mgr is not null); は、2件。 という結果になるのですが、これで理解できるんじゃないですか?

共感・感謝の気持ちを伝えよう!

質問者からの補足

回答ありがとうございます。 しかし、私の理解不足ですが (select mgr from emp where mgr is not null); はnull以外のmgrを検索するので1000と1030が検索され、 結果、empnoが1010と1050の2件 と同じ答えになってしまいます。 nullが検索されるとなぜ0件なのか教えていただけますでしょうか。

関連するQ&A

  • updateについて

    下記、SQLコマンドを実行するとMERTINの歩合給がSMITHのSALに格納されません。実行後、NULLが入ってしまいます。 ちゃんとemp表のMERTINのCOMMには値が入っているのになぜ実行結果がうまくいかないのでしょうか? 回答のほどよろしくお願い致します。 update w_emp set sal = (select comm from emp where ename = 'MERTIN') where sal < 1000 SQL> select * from w_emp; DEPTNO EMPNO ENAME JOB SAL 20 7902 FORD ANALYST 3000 20 7369 SMITH CLERK 10行が選択されました。 SQL> desc w_emp; 名前 NULL? 型 DEPTNO NOT NULL NUMBER(2) EMPNO NOT NULL NUMBER(4) ENAME VARCHAR2(10) JOB VARCHAR2(9) SAL NUMBER(7,2) SQL> desc emp; 名前 NULL? 型 EMPNO NOT NULL NUMBER(4) ENAME VARCHAR2(10) JOB VARCHAR2(9) MGR NUMBER(4) HIREDATE DATE SAL NUMBER(7,2) COMM NUMBER(7,2) DEPTNO NOT NULL NUMBER(2)

  • エラー2「無効な識別子です」

    ORA-00904: "D"."DEPT": 無効な識別子です。 先ほども似たような質問をしましたが原因がよく分からないなのでご存知の方教えていただければ幸いです。 SELECT D.DEPTNO, E.ENAME, E.SAL FROM EMP E, DEPT D WHERE E.SAL >ANY (SELECT MAX(E.SAL) FROM DEPT D, EMP E GROUP BY D.DEPT) SQL> DESCRIBE EMP; 名前 NULL? 型 ----------------------------------------- -------- ---------------------------- EMPNO NOT NULL NUMBER(4) ENAME VARCHAR2(10) JOB VARCHAR2(9) MGR NUMBER(4) HIREDATE DATE SAL NUMBER(7,2) COMM NUMBER(7,2) DEPTNO NOT NULL NUMBER(2) SQL> DESCRIBE DEPT; 名前 NULL? 型 ----------------------------------------- -------- ---------------------------- DEPTNO NOT NULL NUMBER(2) DNAME VARCHAR2(14) LOC VARCHAR2(13)

  • 表の結合に関する質問

    EMP表 EMPNO ENAME JOBNO SAL DEPTNO ----- ------ ------ ----- ------ 1000 ADAMS 100 1000 10 1010 MILLER 200 1200 10 1020 SCOTT 100 800 30 DEPT表 DEPTNO DNAME EMPNO ----- ------ ------ 10 PERSONNEL 1000 20 ACCOUNT 30 DESIGN 上記表に対して、 [SQLコマンド] select e.empno , e.ename , dname , m.ename from emp e join dept d using(deptno) left outer join emp m on d.empno = m.empno; のSQL文を打つと、 EMPNO ENAME DNAME ENAME ----- ------ ------ ----- 1000 ADAMS PERSONNEL ADAMS 1010 MILLER PERSONNEL ADAMS 1020 SCOTT DESIGN と表示されますが、これが表示される過程がわからないです。 emp表とdep表をdeptno列で結合 from emp e join dept d using(deptno) この結合により EMPNO ENAME DNAME ・・・・・・ ----- ------ ------ ----- 1000 ADAMS PERSONNEL ・・・・・・ 1010 MILLER PERSONNEL ・・・・・・ 1020 SCOTT DESIGN ・・・・・・ となります。この部分は分かりますが、 次の、この表とemp表をempnoで結合 left outer join emp m on d.empno = m.empno; した際に、 EMPNO ENAME DNAME ENAME ----- ------ ------ ----- 1000 ADAMS PERSONNEL ADAMS 1010 MILLER PERSONNEL ADAMS 1020 SCOTT DESIGN となりますが、ENAME(4番目の列)で ADAMSと表示される過程が見えてきません。 この部分の過程について、ご教授の程お願い致します。

  • 翔泳社オラクルマスター教科書Silver

    翔泳社オラクルマスター教科書Silverを使ってシルバー取得の勉強をしていますが、どうもこの本の解答に納得のいかない点が多すぎで、このあいだから立て続けに質問してしまってごめんなさい。 何しろ知識が無さ過ぎて、本があっているのか、自分がおかしいのか、判断しかねるのです。 で、今日はこの問題です。 ---問題ここから--- 次の結合文の中で実行時にエラーになるものをひとつ選びなさい a.SELECT DEPT.DEPTNO,EMP.ENAME FROM DEPT D,EMP E WHERE DEPT.DEPTNO=EMP.DEPTNO; b.SELECT ENAME,SAL,GRADE FROM SALGTADE,EMP WHERE SAL>=LOSAL AND SAL<=HISAL; c.SELECT DEPT.DEPTNO,DMP.ENAME FROM DEPT,EMP WHERE DEPT.DEPTNO(+)=EMP.DEPTNO; D.SELECT D.DEPTNO,E.ENAME FROM DEPT D,EMP E WHERE D.DEPTNO=E.DEPTNO; ----問題ここまで---- で、この答えが選択肢aとなっているのですが、納得できません。 解説によれば、「FROM句で二つ以上の表を指定した場合、SELECT句やWHERE句で指定する列名は、どの表の列か判断できなければいけません。」 とあります。 つまり、正解は「どの表か明示的に表示していない」選択肢b だと思うのですが、やはり教科書があっていますか?? 私の考え方はどう間違っているのか、教えていただけたら嬉しいです。 どうかよろしくお願い致します☆

  • グループ関数の問題でエラー!

    下記実行結果により、エラーが出現して困っている次第です。 回答のほどよろしくお願い致します。 SQL> describe emp; 名前 NULL? 型 ------------------------------ EMPNO  NOT NULL NUMBER(4) ENAME      VARCHAR2(10) JOB VARCHAR2(9) MGR NUMBER(4) HIREDATE DATE SAL NUMBER(7,2) COMM NUMBER(7,2) DEPTNO   NOT NULL NUMBER(2) 問1:EMP表より入社年、職種ごとの平均給与を表示しなさい。 平均給与は少数第2位を四捨五入して、$、3桁区切りカンマで表示 SELECT HIREDATE AS 入社年, JOB AS 職種 , TO_CHAR(ROUND(SAL,1),'$9,999') AS 平均給与 FROM EMP GROUP BY HIREDATE,JOB ORA-00979: GROUP BYの式ではありません 問2:上司番号と、その上司の部下の中で給与が最低である従業員の給与を表示しなさい。 上司が存在しない従業員を除き、最低給与が1000ドル以下のグループも除外とし、結果を表示。 SELECT MGR AS 上司番号, MIN(SAL) AS 最低給与, FROM EMP WHERE MGR NOT IS NULL GROUP BY MGR HAVING 1000 < SAL ORA-00936: 式がありません。

  • ANDとORの正確な理解が出来ません。。

    ANDとORの正確な理解が出来ません。。 お世話になっております。 現在、翔泳社の黒本を参考書にOracle11gのSQL基礎Iの学習をしております。 1点、どうしても参考書の解説を読んでも理解できない問題がありまして、 質問いたします。 問題:次のSQL文と同じ結果になるものはどちらか選びなさい SELECT * FROM EMP WHERE DEPTNO NOT IN (10,20); a.SELECT * FROM EMP WHERE DEPTNO <>10 or DEPTNO <> 20; b.SELECT * FROM EMP WHERE DEPTNO <>10 AND DEPTNO <> 20; (正答はb.) 問題のSQL文のWHERE句は「DEPTNOが10でも20でもない物」を取ると理解しています。 そしてa.の文は「10でない、または20でない」、 b.の文は「10でない、かつ20でない」、 と理解しています。 テーブルの中にDEPTNOの値が 「5,10,15,20,25」だったとして、 問題文もa.もb.も5,15,25が取られるのではないか? なぜb.のみが正解なのか?どうしても理解できません。 どういうレコードがあるとき、a. と b.の結果は変わるのでしょうか? 基本的な質問をしてしまいますが、宜しくお願いします。

  • DB2のSQL

    select * from xTABLE where EMP_ID = "P001" というSQLを実行すると SQL0206N "P001" is not valid in the context where it is used. SQLSTATE=42703 のエラーが出ます。 SQLSTATEで調べても「"P001"の列がテーブルにない」ということみたいですが 列名で捉えている時点でおかしい気がします select * from xTABLE where EMP_ID = null のSQLは正常にテーブルのSELECT結果が返ってきます。 どうすればよいでしょうか?

  • 外部結合について

    以下のSQLの2つの結果は同じでしょうか? LEFT OUTHERは、ON句の中の左の表を全て取得するというものでしょうか? SELECT ename, dname, jname FROM emp e LEFT OUTHER JOIN dept d ON (e.deptno=d.deptno) LEFT OUTHER JOIN job j ON (e.jobid=j.deptno); SELECT ename, dname, jname FROM emp e RIGHT OUTHER JOIN dept d ON (d.deptno=e.deptno) RIGHT OUTHER JOIN job j ON (j.jobid=e.deptno); よろしくお願いします。

  • SQL 副問い合わせ使い方について

    初心者です。 フォームに入力された、EMPNOとEMP_IDに一致するデータ(複数の場合あり)を取得するSQL文なのですが、参考にしようとしているコードがいまいち理解できなくて困っています。特にグループ化と結合のあたりがよくわかりません。どなたか、詳しく教えていただけないでしょうか?よろしくお願いします SELECT EMPINFO_A.EMPNO, EMPINFO_A.EMP_ID, EMPCD_CDA.CDA_NAME || EMPCD_CDB.CDB_NAME AS EMPCD_CDNM, NVL(EMPINFO_MAP_VIRTUAL.EMPINFO_COUNT, 0) AS EMPINFO_MAP_COUNT FROM EMPINFO_A, EMPCD_CDA, EMPCD_CDB (SELECT COUNT(*) AS EMPINFO_MAP_COUNT, EMPNO,EMP_ID FROM EMPINF0_MAP WHERE EMPNO = :P_EMPNO AND EMP_ID = :P_EMP_ID GROUP BY EMPNO, EMP_ID) EMPINFO_MAP_VIRTUAL WHERE EMPINFO_A._EMPNO = :P_EMPNO AND EMPINFO_A.EMP_ID = :P_EMP_ID AND EMPINFO_A.EMPNO = EMPINFO_MAP_VIRTUAL.EMPNO(+) AND EMPINFO_A.EMP_ID = EEMPINFO_MAP_VIRTUAL.EMP_ID(+)

  • IN句に副問合わせを使う場合と使わない場合

    お世話になります。 SQLについての質問です。 RDBMSはSymfowareです。 IN句に副問い合わせを指定するSQLと その副問い合わせの結果を直接IN句に記載したSQLで 結果が異なってしまいます。 こういうことってありますでしょうか。 以下のようなSQLです。 (1) SELECT * FROM T1 WHERE T1.column_A IN ( SELECT T2.column_A FROM T2 WHERE T2.column_B='XXXX' ) 上記IN句内のSELECT文の結果は、'A'、'B'、'C'、'D'です。 (2) SELECT * FROM T1 WHERE T1.column_A IN ('A','B','C','D') この(1)、(2)のSQLの結果が異なってしまいます。 私の環境では(1)では0件、(2)では2件ヒットします。 なぜこのようになるのかわかる方がいらっしゃいましたら ご教授ください。 ちなみに、DBを操作して、副問い合わせのSELECT文の結果を 'A'、'B'とすると同じ結果が得られます。 副問い合わせのSELECT文の結果が3件以上になると(1)のSQLの 結果は0件になってしまいます。 RDBMSの障害でしょうか・・・? それとも、IN句に副問い合わせを使用する場合、 その副問い合わせの結果は2件以下にする必要がある なんてルールがあったりするのでしょうか。