DB〜過去問SQL問題まとめ【データベーススペシャリスト試験】

DB

ここでは、DB試験合格に向けて、「SQL」が苦手な人に向けて、SQL問題が出題されている午後1の過去問を纏めました。

R06PM1問2

【R06PM1問2】<SQL2>
SQL2は、エリアごとの在籍者増減数を求めるSQLだ。
①で、’入室’状態の人を1とし、その合計を求め、
②の’退室’状態の人の合計を①から減算し、在籍者増減数を算出している。
①【a;SUM】(CASE WHEN 【b;入退室ログ=’1’】 THEN 1 ELSE 0 )
②ー 【a;SUM】(CASE WHEN 【b;入退室ログ=’0’】 THEN 1 ELSE 0 ) AS 在籍者増減数

<SQL4>
SQL4では、従業員ごとの「最新」の入退室ログのログIDを取得するSQL。
SELECT 従業員番号,【d;MAX(ログID)】FROM 入退室ログ

<SQL5>
SQL5は、入室している従業員のログIDのエリアコードを取得するSQLである。
「CASE WHEN 【b;入退室ログ=’1’】THEN エリアコードELSE ‘9999’ END AS エリアコード」で’入室’状態の時、エリアコードを挿入、’退室’の時、’9999’を挿入し、それらをエリアコードと呼んでいる。
また、「WHERE ログID=:HCURRENTID」でログIDが現時点でのログIDに限定している。
SELECT CASE WHEN 【b;入退室ログ=’1’】THEN エリアコード ELSE ‘9999’ END AS エリアコード FROM 入退室ログ WHERE ログID=:HCURRENTID

【R06PM1問2】③

①WHERE 従業員番号 
 BETWEEN 【e;:HTARGETID】 AND 【f;:HENDID】 
②AND 年月日 BETWEEN :HBEGINDAY AND :HENDDAY
③AND 上長承認=’Y’ AND 監査結果 【g;IS NULL】
④ORDER BY 【h;従業員番号】,年月日

①では、再開位置の開始のID;HTARGETID〜終了のID;HENDIDの間で設定している。処理対象の従業員の範囲がHBEGINIDから再開位置のHTARGETIDに更新されている点に注意が必要。

R06PM1問3

【R06PM1問3】
SELECT 組織コード,A.従業員コード,COALESCE(SUM(計画時間),0)AS 計画時間合計,
NTILE(3) OVER (PARTITION BY 【ア;組織コード】 ORDER BY 【イ;COALESCE(SUM(計画時間),0)】) AS 時間階級, 
RANK() OVER ( ORDER BY 【イ;計画時間】 ) AS 時間ランク 
FROM 【ウ;従業員】 A LEFT OUTER JOIN 【エ;稼働計画】 B
 ON A.従業員コード=B.従業員コード AND 計画年=’2024’ AND 計画月=’11’ 
WHERE 役職コード=’SE’
GROUP BY 組織コード,A.従業員コード ORDER BY 組織コード,時間ランク,A.従業員コード

「COALESCE(SUM(計画時間),0)」で、計画時間が入っている従業員は、計画時間の合計を算出し、計画時間が入っていない(NULL)の従業員は計画時間を’0’としている。NULLではだめなのか?

ポイント

SUMとCOUNT

項目SUM(表現)COUNT(表現)
主な機能式の結果を合計するNULLではない行の数を数える。
集計したい時CASE文の戻り値を 1 にする。CASE文の戻り値を 1 にする。
集計したくない時CASE文の戻り値を 0 にする。CASE文の戻り値を NULL にする。
計算の仕組み1 と 0 を足し合わせ、1 の個数を求める。1 の個数を数え、NULLの行を無視する
例文 (SQL2)SUM(CASE WHEN 入退室ログ = ’1’ THEN 1 **ELSE 0** END)COUNT(CASE WHEN 入退室ログ = ’1’ THEN 1 **ELSE NULL** END)
メリット1 と 0 の組み合わせは直感的で、条件付き集計で最も一般的COUNT(*)と同じく行を数える機能を利用する、論理的な記述。
注意点0 以外(例: 5)を集計すると、合計値が 5 ずつ増えてしまう。ELSE 0 にすると 0 がカウントされ、常に全行数になってしまう。

COALESCE(SUM(計画時間),0)で’0’にする理由

項目内容
1. NULLだと比較できないSUM(計画時間) がすべてNULL(つまり計画なし)の場合、結果もNULLになります。NULLは「値がない」扱いなので、RANK()NTILE() は順位づけやグループ分けができません。
2. 0に変換すれば比較可能COALESCE(..., 0) により「NULL → 0」に変換しておくことで、他の従業員との比較が可能になります。つまり「計画がない人=計画時間0」として扱えるようになります。
3. 集計結果にも影響例えば AVG()ORDER BY でも、NULLをそのままにしておくと扱いにくい(ソート順が最後・除外される等)ため、0に変換しておくのが実務的です。

R05問3

【R05PM1問3】表3
圃場ごと、農事日付ごとに1日の平均温度と行数を調べるSQL。
<SQL1>
WITH R ( 圃場ID、農事日付、日平均温度、行数) AS( SELECT 【a;圃場ID、農事日付、AVG(分平均温度)】、COUNT(*) FROM 観測 GROUP BY 【b;圃場ID、農事日付】) 
SELECT * FROM R

【R05PM1問3】表5
指定した農事日付の期間について、圃場ごと農事日付ごとの積算温度を調べるSQL。
WITH R ( 圃場ID、農事日付、日平均温度、行数 ) AS ([非表示])
SELECT 圃場ID、農事日付、SUM(【f;日平均温度】)
OVER ( PARTITION BY 【g;圃場ID】 ORDER BY 【h;圃場ID、農事日付】
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS 積算温度
FROM R WHERE 農事日付 BETWEEN :h1 AND :h2

処理内容ポイント・解説
WITH R (圃場ID, 農事日付, 日平均温度, 行数) AS (...)事前に作成したCTE R を参照前問で作成した「圃場ごと・日ごとの日平均温度・行数」を格納した仮テーブル
SELECT 圃場ID, 農事日付, SUM(日平均温度) OVER (...) AS 積算温度積算温度(累積温度)を計算ウィンドウ関数 SUM() OVER() を使用。累積計算することで、指定期間内の積算温度を求める
PARTITION BY 圃場ID圃場ごとに累積計算を区切る圃場ごとに別々に累積するため、他圃場のデータは混ざらない
ORDER BY 圃場ID, 農事日付農事日付順に累積日付順に積算されることで、「今日までの累計温度」を取得
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW現在行までの全行を対象「その日の前日まで+当日」を範囲として累積計算する
FROM R WHERE 農事日付 BETWEEN :h1 AND :h2指定期間のデータのみ抽出不要な日付データは対象外にして、効率的に集計

ポイント

💡 SQLのWITH句(共通テーブル式)の処理フロー

ステップSQLの記述要素処理内容役割とブログ向け解説ポイント
ステップ 1WITH R (列名...) AS (仮想テーブル(CTE)を**R**と命名し、最終的な列名(例:日平均温度)を定義します。【設計図の作成】 複雑な計算結果に分かりやすい名前をつけ、メインクエリでの利用に備えます。
ステップ 2FROM 観測データの元となる**「観測」テーブル**を指定します。【データの取得元】 どのテーブルのデータを使うかを定義します。
ステップ 3GROUP BY 圃場ID, 農事日付観測データを、指定されたキー(圃場ID農事日付)の単位でグループ化します。【集計単位の決定】 この単位(例:「圃場Aの10月1日」)で後の計算が実行されます。
ステップ 4SELECT ... AVG(分平均温度), COUNT(*)GROUP BYで区切られた各グループに対して、集計関数AVGCOUNT)を実行し、計算結果を仮想テーブル R の列に割り当ててデータを作成します。【データの生成と計算】 分単位の細かいデータを、**「日平均温度」「観測回数」**といったサマリー情報に変換する、集計の核心となる部分です。
ステップ 5SELECT * FROM Rデータが格納された一時テーブル R から、すべての列を選択し、最終的な結果セットとして出力します。【結果の表示】 WITH句の処理が完了した後、その結果をあたかも通常のテーブルのように扱って表示する部分です。
処理内容ポイント・解説
WITH R (圃場ID, 農事日付, 日平均温度, 行数) AS (...)事前に作成したCTE R を参照前問で作成した「圃場ごと・日ごとの日平均温度・行数」を格納した仮テーブル
SELECT 圃場ID, 農事日付, SUM(日平均温度) OVER (...) AS 積算温度積算温度(累積温度)を計算ウィンドウ関数 SUM() OVER() を使用。累積計算することで、指定期間内の積算温度を求める
PARTITION BY 圃場ID圃場ごとに累積計算を区切る圃場ごとに別々に累積するため、他圃場のデータは混ざらない
ORDER BY 圃場ID, 農事日付農事日付順に累積日付順に積算されることで、「今日までの累計温度」を取得
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW現在行までの全行を対象「その日の前日まで+当日」を範囲として累積計算する
FROM R WHERE 農事日付 BETWEEN :h1 AND :h2指定期間のデータのみ抽出不要な日付データは対象外にして、効率的に集計

移動平均の算出SQL;ROWS BETWEEN UNBOUNDED PRECENGING AND N PRECEDING

構文意味用途と処理の例
ROWSフレームの定義を物理的な行数に基づいて行います。行数やオフセット(前後何行)に基づいて集計範囲を厳密に制御したい場合に使用します。
BETWEEN ... AND ...フレームの開始位置終了位置を定義します。積算や移動平均など、フレームに明確な範囲を持たせる場合に必須です。
UNBOUNDED PRECEDINGフレームの開始位置:パーティションの最初の行積算 (Running Total) の開始点として使用されます。
CURRENT ROWフレームの終了位置現在処理中の行積算の場合、UNBOUNDED PRECEDINGと組み合わせることで、「最初から現在まで」を意味します。
N PRECEDINGフレームの開始位置または終了位置:現在の行より N 行前移動平均の計算で開始点として使用されます。
N FOLLOWINGフレームの開始位置または終了位置:現在の行より N 行後未来のデータを含めた集計で終了点として使用されます。
【例文 SQL 1】ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING**現在の行を含め、前後 2 行(計 5 行)**のデータで集計を行います。移動平均などの計算で使用されます。
【例文 SQL 2】ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWINGフレームの範囲を、パーティションの**最初から最後までの「全行」**に設定します。

R04問2

【R04PM1問2】図2
SELECT A.モデル名 AS 新モデル名、C.モデル名 AS 旧モデル名、A.定価 AS 新定価、C.定価 AS 旧定価
FROM 見積回答明細 A INNER JOIN 見積回答 B ON A.見積依頼番号=B.見積依頼番号
INNER JOIN 商品 C ON A.【a;商品コード】 = C.【a;商品コード】
WHERE B.見積回答日 > C.更新日
 AND (A.モデル名 <> C.モデル名 【b;OR】 A.定価 <> C.定価

・【a;】には、商品テーブルと見積回答明細テーブルの結合条件の列名が入る。両テーブルに共通している、’商品コード’が入る。
・INNNER JOINを使う理由は、見積時点で、モデル名、定価を更新したものだけ、更新すれば良いので、
LEFT OUTER JOINでは、すべての「見積回答明細」が含まれ、見積回答に使われていない「商品」は含まれない。(そのような場合は滅多にないと思うので、どちらでも良いと思うが)
RIGHT OUTER JOINでは、すべての「商品」が含まれ、見積回答に使われていない商品すべてを含み、冗長になる。(見積しない商品など、通常は考えにくいので、これでも良いと思う。)

【R04PM1問2】表2
<SQL1>
ALTER TABLE 商品 ADD COLUMN 適用開始日 DATE DEFAULT CURRENT_DATE NOT NULL;
ALTER TABLE 商品 ADD COLUMN 適用終了日 DATE;
CREATE TABLE 商品履歴 LIKE 商品;
ALTER TABLE 商品履歴 ADD PRIMARY KEY (【c;商品コード】、【d;適用開始日】);

サブタイプ貸した場合の主キーの選定の問題。スーパータイプの主キーに倣って設定する。

<SQL2>
CREATE TRIGGER トリガー1 【e;BEFORE】 UPDATE ON 商品
 REFERENCING OLD AS OLD1 NEW AS NEW1 FOR EACH ROW
 SET NEW1.適用開始日=COALESCE(NEW1.適用開始日、CURRENT_DATE);
CREATE TRIGGER トリガー2 【f;AFTER】 UPDATE ON 商品
 REFERENCING OLD AS OLD2 NEW AS NEW2 FOR EACH ROW
 INSERT INTO 商品履歴
 VALUES(OLD2.商品コード、OLD2.メーカー名、OLD2.商品名、OLD2.モデル名、OLD2.定価、OLD2.更新日、【g;OLD2】.適用開始日、ADD_DAYS(【h;NEW2】.適用開始日、-1));

【e;】は商品テーブルでUPDATEする契機を入れる。
 更新時(NEW1)の行に対して、新しい値にしたいので、『BEFORE』となる。
 AFTERの場合、値の更新ができない。
【f;】は商品テーブルでUPDATEする契機を入れる。
 更新時に行の挿入をしたいので、『AFTER』となる。
 BSFOREの場合、更新時に行の挿入ができない。
【g;】は、商品履歴に挿入する列名の一部を入れる。
 更新時に入れるべき適用開始日は、更新前の情報なので『OLD2』となる。
【h;】は、商品履歴に挿入する列名の一部を入れる。
 更新時に適用開始日-1として、入れたいのは、更新後の情報の1日前の値なので、『NEW2』となる。

NEW、NEW1、NEW2やOLD、OLD1、OLD2の違いは、
NEW・OLD;商品テーブルの更新後と更新前の元の値としている。
NEW1・OLD1;適用開始日を更新するために設定している。→商品テーブル側への反映のため。
NEW2・OLD2;商品履歴テーブルに挿入するために2として新たに名称を変えている→商品履歴テーブル側への反映のため。
つまり、NEW1・OLD1とNEW2・OLD2で分けているのは、商品テーブルへの反映と商品履歴テーブルの反映で分けているから。
同じ場合はどうなるのか?トリガーのタイミング違うので、設定できない?
→設定可能だが、混同を避けるために推奨されない。

処理内容ポイント・解説
ALTER TABLE 商品 ADD COLUMN 適用開始日 DATE DEFAULT CURRENT_DATE NOT NULL;商品テーブルに「適用開始日」を追加更新時に日付を自動で入れるため、NULL不可・デフォルトを現在日付に設定
ALTER TABLE 商品 ADD COLUMN 適用終了日 DATE;商品テーブルに「適用終了日」を追加履歴管理の終了日を保持
CREATE TABLE 商品履歴 LIKE 商品;商品履歴テーブルを作成商品テーブルと同構造の履歴用テーブル
ALTER TABLE 商品履歴 ADD PRIMARY KEY (商品コード, 適用開始日);商品履歴の主キーを設定サブタイプでもスーパータイプの主キーに倣って、商品コード+適用開始日で一意性を確保
CREATE TRIGGER トリガー1 BEFORE UPDATE ON 商品 ...商品テーブル更新前に適用開始日を補完BEFORE トリガーで更新前に NEW1.適用開始日をセット(NULLの場合はCURRENT_DATE)
CREATE TRIGGER トリガー2 AFTER UPDATE ON 商品 ...商品テーブル更新後に履歴を挿入AFTER トリガーで旧データ(OLD2)を商品履歴テーブルに挿入。適用終了日を更新後の適用開始日-1で設定
NEW1・OLD1 / NEW2・OLD2 の使い分けNEW1/OLD1は商品テーブル側、NEW2/OLD2は履歴テーブル側– 商品テーブルに反映させる値と履歴テーブルに挿入する値でタイミングが異なるため別名を使用- BEFOREとAFTERで処理タイミングが違うため、同じ名称は使用できない
トリガーのタイミングBEFORE: 商品テーブルの値を変更するAFTER: 履歴テーブルに挿入するBEFOREトリガーでは履歴挿入はできない、AFTERでは商品テーブルの値変更はできない


ポイント

トリガータイミングの理解;BEFORE vs AFTER

箇所解答処理とタイミングの必然性
eBEFORE商品の行が更新される前に実行されます。NEW1.適用開始日のように**NEW行の値を変更し、その変更を商品テーブルに反映させるには、必ずBEFORE**タイミングである必要があります。AFTERではNEW行の変更は反映されません。
fAFTER商品の行が更新された後に実行されます。履歴(OLD2の情報)を挿入する処理は、商品テーブルの更新が確実に完了した後に行うのが安全で自然です。BEFOREでも挿入は可能ですが、商品テーブルの値を参照する処理履歴ログの挿入は通常AFTERに行います。

エイリアス分け;NEW1・OLD1とNEW2・OLD2

エイリアス使用トリガー処理目的役割の明確化
OLD1, NEW1BEFORE トリガー商品テーブルの適用開始日を決定 (NEW1に値を設定)商品テーブル側への反映という役割を明確にしています。
OLD2, NEW2AFTER トリガー商品履歴テーブルに行を挿入 (OLD2の値で履歴行を作成)履歴テーブル側への反映という役割を明確にしています。

R04問3

【R04PM1問3】表4
WITH TEMP (出庫番号、ピッカーID、棚番号、商品コード、出庫時刻、出庫間隔時間) AS
(SELECT A.出庫番号、A.ピッカーID、B.棚番号、B.商品コード、B.出庫時刻、B.出庫時刻 – COALESCE( LAG(B.出庫時刻) OVER ( PARTITION BY 【x;】 ORDER BY B.出庫時刻)、A.出庫開始時刻 )AS 出庫間隔時間
FROM 出庫 A JOIN 出庫指示 B ON A.出庫番号=B.出庫番号 AND 出庫日ーCAST( :h AS DATE) )
GROUP BY 棚番号、商品コード ORDER BY 出庫間隔時間合計 DESC
【x】に入れる値
【あ】;棚の前での待ち時間を含むが、商品の梱包及び出荷担当者への受け渡しにかかった時間も含まれる。→『A.ピッカーID』
<解説>
ピッカーID単位での区分けとなり、ピッカーIDごとの業務の開始〜終了の時間で計測する。
よって、「出庫番号割当て→ピッカー移動→棚での商品ピッキング→担当者への受渡し・梱包→終了後、次の出庫番号の割当て〜以降順次」のように、ピッカーIDに紐づく棚番号ごと、商品ごとの時間で合計される。

【い】;棚の前での待ち時間が含まれない。→『B.棚番号』
<解説>
棚番号ごとの区分けとなり、棚番号の開始〜終了までの時間で計測する。
よって、「棚から商品のピッキング→担当者への受渡し・梱包→終了後、次の出庫番号の割当て」のように、1つの棚番号に対する時間で合計される。

【x】;特定の棚の前での待ち時間を実証する→『B.出庫番号』
<解説>
出庫番号ごとの区分けとなり、出庫番号の開始〜終了までの時間で計測する。
よって、「出庫番号の割当て→ピッカー移動→棚での商品ピッキング→担当者への受渡し・梱包→終了後、次の出庫番号の割当て」のように、出庫番号が変わるまでの間で棚番号ごと、商品ごとの時間で合計される。
(出庫指示の業務範囲として、出庫番号割当て〜担当者への受渡しまでの記載がないと成立しない)

ポイント

選定するキー列による違い

区分【x】に入る値分析対象の単位含まれる時間の範囲処理イメージ(業務の流れ)解説ポイント
【あ】A.ピッカーIDピッカー単位棚前での待ち時間+梱包・受渡し時間を含む出庫番号割当て → ピッカー移動 → 棚でピッキング → 受渡し・梱包 → 次の出庫番号ピッカーIDごとの出庫作業全体を計測。ピッカー単位の稼働効率や作業負荷を分析できる。
【い】B.棚番号棚単位棚前の待ち時間を含まない(棚作業のみ)棚からピッキング → 受渡し・梱包 → 次の棚作業へ棚番号ごとの作業時間を把握でき、ボトルネック棚(作業が集中する棚)の特定に使える。
【う】B.出庫番号出庫番号単位棚前での待ち時間を実証(特定出庫に限定)出庫番号割当て → ピッカー移動 → 棚でピッキング → 受渡し・梱包 → 次の出庫番号出庫番号ごとの業務サイクルを追跡。個別案件単位での作業効率比較や実証分析に適している。

SQLの詳細

SQL要素内容解説
WITH TEMP (…) AS (SELECT …)一時ビューTEMPを作成出庫番号・棚番号・商品コードごとの出庫データを抽出
LAG(B.出庫時刻) OVER (PARTITION BY 【x】 ORDER BY B.出庫時刻)前回の出庫時刻を取得【x】で指定した単位(ピッカー・棚・出庫番号)ごとに直前の出庫時刻を参照
COALESCE(…, A.出庫開始時刻)NULL時は出庫開始時刻を代入最初の出庫(LAGがNULLになる場合)に対応
出庫時刻 - COALESCE(…)出庫間隔時間を算出現在の出庫と直前の出庫の時間差を計算

R03問3

【R03問3】表3
WITH TEMP (TOTAL) AS (SELECT COUNT(*) FROM 物件)
SELECT 沿線、FLOOR 【ハ;COUNT (*)】 * 100 / 【二;TOTAL】)
FROM 物件 CROSS JOIN TEMP
WHERE エアコン=’1’ AND オートロック=’1’
GROUP BY 【ホ;沿線、TOTAL】

【ハ;COUNT (*)】は、WHERE句での条件でのカウント。
WITH TEMPのTOTALは、物件テーブルでの総数のカウントという違いがある。

項目内容補足・ポイント
WITH句(TEMP)SELECT COUNT(*) FROM 物件物件テーブル全体の総件数(=分母)を算出。サブクエリを名前付きテーブル(TEMP)として扱う。
CROSS JOIN TEMPFROM 物件 CROSS JOIN TEMPTEMPの集計結果(総数)を、物件テーブルの各行に結合。全件数を各行で参照できるようにする。
WHERE句エアコン='1' AND オートロック='1'条件を満たす物件のみを対象(=分子の範囲)。
GROUP BY句沿線, TOTAL沿線ごとにグループ化し、TEMPのTOTALを保持。
SELECT句沿線, FLOOR(COUNT(*) * 100 / TOTAL)条件を満たす物件の**割合(%)**を算出。COUNT(*)が分子、TOTALが分母。FLOORで小数点以下切り捨て。
【ハ】COUNT(*)WHERE句での条件(エアコン・オートロック)を満たす件数分子のカウント。
【二】TOTAL物件テーブル全体の件数(WITH句で算出)分母のカウント。

【R03問3】表4
INSERT INTO 物件設備 ( 物件コード、設備コード、設備済個数 )
SELECT 【a;物件コード、’A1’、1】 FROM 物件 WHERE 【b;エアコン=’Y’】
【c;UNION】 SELECT 【d;物件コード、’A2’、1】 FROM 物件 WHERE 【e;オートロック=’Y’】

処理手順SQL文の流れ処理内容のイメージ
SELECT 物件コード, 'A1', 1 FROM 物件 WHERE エアコン='Y'エアコン付き物件の一覧を作成
UNION SELECT 物件コード, 'A2', 1 FROM 物件 WHERE オートロック='Y'オートロック付き物件を追加し、重複を除去
INSERT INTO 物件設備 (...)上記の結果を物件設備テーブルに一括登録
構文役割・機能この問題での使われ方ポイント・注意点
INSERT INTO既存テーブルに新しい行を追加する物件設備 テーブルに、条件に合う設備情報(物件コード+設備コード+設備済個数)を追加しているデータ登録用。VALUESの代わりにSELECT句の結果を挿入している点が特徴。
SELECTテーブルからデータを取得する物件 テーブルから、エアコン='Y'オートロック='Y'の行を選択SELECTの結果を直接INSERTに流し込む構成。抽出条件により異なる設備を判定。
WHERE行を絞り込むWHERE エアコン='Y'WHERE オートロック='Y'条件に合う物件のみを対象。ブール条件で分岐処理を実現。
UNION複数のSELECT結果を1つに結合(重複行は削除)エアコンのSELECT結果と、オートロックのSELECT結果を結合複数設備を一括で登録できるようにしている。重複行を許す場合はUNION ALL
VALUES直接値を指定して挿入する今回は使用していない小規模挿入では使うが、今回はSELECT結果を使うため不要。
FROM参照元テーブルを指定FROM 物件今回は1つのテーブルのみ参照。JOIN不要。
テーブル別名テーブル名を短くして可読性を上げる今回は明示的に使用していない(例:物件 AS Pなども可)複数テーブルをJOINする場合は必須。単一テーブルでは省略可。

【R03問3】表6
<SQL6>
SELECT B.物件コード、B.物件名
FROM 新物件 B
【f;INNER JOIN】物件設備 BS1 ON B.物件コード = BS1.物件コード AND B.沿線 = ’○△線’
【g;INNER JOIN】設備 S1    ON BS1.設備コード = S1.設備コード AND 【h;S1.設備コード=’A1’】
【f;INNER JOIN】物件設備 BS2 ON B.物件コード = BS2.物件コード
【g;INNER JOIN】設備 S2   ON BS2.設備コード = S2.設備コード AND 【i;S2.設備コード=’A2’】 

<SQL7>
SELECT DISTINCT B.物件コード、B.物件名
FROM 新物件 B
【f;INNER JOIN】物件設備 BS ON B.物件コード = BS.物件コード AND B.沿線 = ’○△線’
【g;INNER JOIN】設備 S   ON BS.設備コード = S.設備コード AND 【j;BS.設備コード=’A1’ OR BS.設備コード=’A2’】

区分構文・句役割・機能SQL6での使われ方SQL7での使われ方補足ポイント
【f】INNER JOIN(内部結合)両方のテーブルに存在するデータだけを取得新物件Bと物件設備BS1・BS2を、物件コードで結合している同様に、新物件Bと物件設備BSを結合結合条件を満たすデータのみ対象。設備を持たない物件は除外される。
【g】INNER JOIN(続き)結合した設備テーブルの内容を取り込む設備S1, S2をそれぞれ結合して設備情報を取得設備Sを結合して設備コードを参照設備名やコードなど、マスタ的情報を参照するために使用。
【h】【i】設備コードの条件指定特定の設備コードを持つ行を選択S1.設備コード='A1'(エアコン)S2.設備コード='A2'(オートロック)—(まとめてORで指定)SQL6では設備ごとにテーブルを分け、両方の条件を満たす物件を抽出。
【j】OR条件(複数指定)複数の設備を1つのテーブル結合で判定BS.設備コード='A1' OR BS.設備コード='A2'SQL7では1回の結合で複数設備をまとめて判定。
DISTINCT重複排除同じ物件が複数設備で重複して出ないようにする使用している(重複防止)OR条件では重複しやすいので必須。
結合数設備テーブル×2(S1, S2)設備テーブル×1SQL6は厳密一致(両方あり)/SQL7はゆるい一致(どちらかあり)。

【R03問3】図3
CREATE VIEW 物件 (物件コード、沿線、エアコンmオートロック) AS
SELECT B.物件コード、B.沿線
 CASE WHEN 【k;BS1.設備コード】 THEN 【l;’Y’】 ELSE 【m;’N’】 END AS エアコン、
 CASE WHEN 【非表示】 THEN 【l;’Y’】 ELSE 【m;’N’】 END AS オートロック
FROM 新物件 B
【n;LEFT OUTER JOIN】 物件設備 BS1 ON B.物件コード = BS1.物件コード AND 【o;BS1.設備コード=’A1’】
【n;LEFT OUTER JOIN】 物件設備 BS2 ON B.物件コード = BS2.物件コード AND 【非表示】

記号対応箇所内容・意味解説
【k】BS1.設備コード条件式(CASEの判定対象)「物件設備」テーブルの設備コードが存在すれば(A1の行があれば)Y、なければNを返す。
【l】'Y'条件成立時の値対象設備(A1またはA2)が存在する場合に「Y」と表示。
【m】'N'条件不成立時の値対象設備が存在しない場合に「N」と表示。
【n】LEFT OUTER JOIN結合の種類「新物件」を基準に、設備が存在しない物件も表示するための左外部結合。
【o】BS1.設備コード='A1'結合条件設備コードA1(エアコン)を対象とする結合。※A2(オートロック)はこの下で同様に設定。
区分処理内容結果の特徴
CREATE VIEW新しい仮想テーブル「物件」を作成実テーブルを直接操作せず、結果を参照できるビューを生成。
SELECT句(CASE WHEN …)各設備コードが存在するかを判定設備あり→‘Y’、なし→‘N’。
LEFT OUTER JOIN「新物件」を基点に「物件設備」を結合設備がない物件も抜け落ちずに表示される。
設備コードの指定(A1/A2)A1=エアコン、A2=オートロック各設備コードをそれぞれの列にマッピング。

R02問2

R02問3

【R02問3】図3

H31問2

H31問3

H30問2

H30問3

H29問2

H29問3

H28問3

H27問2

H27問3

H26問2

H26問3

H25問3

H24問3

H23問3

H22問3

H21問3

H20問3

H19問3

H18問3

H18問4

H17問3

H17問4

H16問2

H15問2

H14問3

コメント

タイトルとURLをコピーしました