初心者です。
フォームに入力された、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(+)
A 回答 (2件)
- 最新から表示
- 回答順に表示
No.2
- 回答日時:
タイプミスと、EMPCD_CDA, EMPCD_CDBに結合条件が指定されていない点は私も気になりました。
#1さんの回答で十分説明されているので、補足みたいなものです。
そもそもGROUP BYする必要があるのかということについですが、
今使われている以下のサブクエリでは、GROUP BYを使っているため、結果は0行または1行です。
GROUP BYを使うと、キー単位にグルーピングする結果、キーのある場合しか結果が返らないからです。
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
一方、単純に件数だけを取るようにすると、対象がなくても「0件」と返ってきますから、結果は必ず1行返ります。
SELECT COUNT(*) AS EMPINFO_MAP_COUNT
FROM EMPINF0_MAP
WHERE EMPNO = :P_EMPNO
AND EMP_ID = :P_EMP_ID
結果が必ず1行返るので、外部結合もNVLをする必要もありません。
その場合はクエリは以下の通りです。
SELECT
EMPINFO_A.EMPNO,
EMPINFO_A.EMP_ID,
EMPCD_CDA.CDA_NAME || EMPCD_CDB.CDB_NAME AS EMPCD_CDNM,
EMPINFO_MAP_VIRTUAL.EMPINFO_COUNT AS EMPINFO_MAP_COUNT
FROM EMPINFO_A, EMPCD_CDA, EMPCD_CDB,
(SELECT COUNT(*) AS EMPINFO_MAP_COUNT
FROM EMPINF0_MAP
WHERE EMPNO = :P_EMPNO
AND EMP_ID = :P_EMP_ID) EMPINFO_MAP_VIRTUAL
WHERE EMPINFO_A._EMPNO = :P_EMPNO
AND EMPINFO_A.EMP_ID = :P_EMP_ID
No.1
- 回答日時:
>特にグループ化と結合のあたりがよくわかりません
「このSQLで、どうして意図した結果が得られるのかがわからない」のか、「グループ化と結合のSQLの基礎的な構文自体がよくわからない」のかがわかりませんが、とりあえず想像で書いて行きます。
まず、マスタテーブルと思われるEMPCD_CDA, EMPCD_CDBを特定する条件が無いので(書き漏れ?)、話をわかりやすくするため、外します。(ついでに明らかな書き間違いも)
・EMPINFO_Aは基本的な社員マスタ?
・EMPINF0_MAPはEMPNO、EMP_IDで社員マスタと紐付くトランザクションかサブマスタ
・フォームの入力値からEMPINFO_Aを表示したい
・EMPINF0_MAPをEMPNO、EMP_ID単位で何件あるかを表示したい
・EMPINF0_MAPは、必ずしも社員全員分の情報があるわけではない
(EMPINFO_Aに紐づくEMPINF0_MAPが無い場合はカウント0で表示)
これが想像される要件です。まず、フォームの入力値からEMPINFO_Aを表示する部分だけ書いてみます。これはわかりますよね。
SELECT EMPINFO_A.EMPNO, EMPINFO_A.EMP_ID
FROM EMPINFO_A
WHERE EMPINFO_A._EMPNO = :P_EMPNO
AND EMPINFO_A.EMP_ID = :P_EMP_ID
次に()で括られたインラインビューEMPINFO_MAP_VIRTUALの部分のみ。
EMPINF0_MAPをEMPNO、EMP_ID単位で何件あるかを取得します。
この「何々単位で集計」と言う要件を満たすために、GROUP BYを使います。
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
この2つを結合したのが以下のSQLになります。
SELECT EMPINFO_A.EMPNO, EMPINFO_A.EMP_ID,
NVL(EMPINFO_MAP_VIRTUAL.EMPINFO_COUNT, 0) AS EMPINFO_MAP_COUNT
FROM EMPINFO_A,
(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 = EMPINFO_MAP_VIRTUAL.EMP_ID(+)
入力値の社員キーでヒットするEMPINF0_MAPは、必ずしも社員全員分の情報があるわけではないですが、入力値の社員キーでヒットするEMPINFO_Aはすべて表示しなければいけません。その場合は、「外部結合」を使うので、EMPINFO_MAP_VIRTUALの結合条件のところに「(+)」を指定します。
外部結合は、ANSI標準の LEFT JOIN で書いた方が、個人的にはわかりやすい気がしますが、バージョンが書かれていないので何とも言えません。
(FORMS側の制限もあるかもしれないし)
外部結合を使うと、「紐付かないデータはNULL」になります。
この場合で言えば、EMPINFO_MAP_VIRTUAL.EMPINFO_COUNTがそれにあたります。
NVLを使って、件数NULLはZEROに補完します。
後は、名称を取得するためのマスタテーブルと思われるEMPCD_CDA, EMPCD_CDBとの結合条件を補完して完成。
(質問のSQLから欠落しているので、何で紐付ければよいかはわかりません)
utakataXEXさま、詳しい説明ありがとうございます!結合条件とか抜けててすみません。書き忘れました。インラインビューのあたりが一番疑問でした。使い方等知らなかったこともあり、ネットで検索する際も的を得ていませんでした。勉強させていただきました。貴重なお時間をありがとうございます!
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) 先ほど、回答者様によって教えていただいたのですがどうしたらいいか分かりません。 ユーザーフォーム上に 2 2023/02/21 22:25
- Access(アクセス) アクセス 有効なフィールド名、または式として認識できませんのエラー 3 2022/08/19 11:53
- Access(アクセス) アクセス where句を使用して複数条件抽出をするには 2 2022/08/29 13:24
- PHP コメント機能に返信欄を矢印で追加したい 1 2022/05/09 21:17
- その他(プログラミング・Web制作) pythonリストの特定の値を表示htmlで表示できない 2 2022/05/14 05:48
- Oracle sqlで質問です。 aテーブルとbテーブルがあり、下記のsqlで取得したidとnameに一致しないレ 1 2022/04/20 20:34
- PostgreSQL 画像とカテゴリーを出力したいのですが、取得の条件を付ける方法がわかりません。 2 2022/05/01 18:03
- MySQL 書籍の内容はまともでしょうか? 1 2023/01/22 03:07
- MySQL SQLです。こんな感じですか?あってますか? うまくいきません教えてくださいお願いします 1 2023/07/08 15:27
- MySQL うまくいきません教えてくださいお願いしますSQLです。クエリ構文です。 1 2023/07/07 12:39
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Excel VBAで、Averageの範囲を...
-
関係演算子が無効です。
-
条件付き外部結合について
-
GROUP BYを行った後に結合した...
-
外部結合とor条件混在の記述方法
-
ACCESSのクエリで同じSQL文だが...
-
Oracleでの文字列連結サイズの上限
-
SELECTで1件のみ取得するには?
-
SELECTの結果で同一行を複数回...
-
select句副問い合わせ 値の個...
-
OracleのSQL*PLUSで、デー...
-
Accessで別テーブルの値をフォ...
-
SQL文で右から1文字だけ削除す...
-
Excelでセルの書式設定を使用し...
-
使うべきでない文字。
-
ADO VBA 実行時エラー3021
-
☆☆☆☆SQL Olacle 3つ以上の文字...
-
DATE型にNULLをセットするには?
-
実績累計の求め方と意味を教え...
-
カレントレコードが無い事を判...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
関係演算子が無効です。
-
SQL 外部結合についての質問
-
Excel VBAで、Averageの範囲を...
-
TO_CHAR関数における外部結合に...
-
同じテーブルをLEFT JOIN
-
自己相関サブクエリと自己結合...
-
LEFT JOINの条件式で=’’を使用...
-
Informixで文字列を数値型に
-
内部結合する時の結合条件と制...
-
Access 結合条件設定方法
-
T-SQL 動的に優先順ごとにデー...
-
WHERE句の書き方
-
エラー「無効な識別子です」
-
エクセルVBAでSUM関数の位置を...
-
Pro*CでVARCHAR2項目の検索
-
エラー2「無効な識別子です」
-
Oracle SQL 結合の手法について
-
【修正希望】【マクロ】元デー...
-
SQLで後方の文字列を置換する方法
-
range表記をcells表記にしたい
おすすめ情報