SSブログ

クエリ グループで最大値をもつレコードの抽出(相関サブクエリ) [クエリ]

 以前の記事で、テーブル全体から最大値をもつレコードを抽出する方法をとりあげましたが、今回はグループ毎の最大値のレコードを抽出します。

 データはこんな感じ。
 担当Aさん、Bさん、Cさん・・・が居て、日付毎に、金額が一番大きかった人のレコードを抽出します。

 まず、以前と同じ考え方でSQLを作成します。
 日付毎に最大の金額を求めるSQLを作成します。

SELECT 日付, Max(T実績.金額) AS 金額
FROM T実績
GROUP BY 日付

 結果は、以下の通り。

 日付と金額が得られたので、これと一致するレコードを抽出するSQLを書けばできあがりです。
 しかし、前回のSQLの、
SELECT 日付, 金額
FROM T売上
WHERE 金額 = ( SELECT MAX( 金額 ) FROM T売上 )

 という方法は、サブクエリの結果が1件のときしか利用できません。今回は、条件にしたい項目も2つあります。
 なので、今回は、WHERE条件ではなく、テーブル結合で抽出します。

SELECT A.日付,A.担当,A.金額
FROM T実績 AS A INNER JOIN
(SELECT T実績.日付, Max(T実績.金額) AS 金額
FROM T実績
GROUP BY T実績.日付) AS B
ON (A.金額 = B.金額) AND (A.日付 = B.日付)


 一致のみで良いので、INNER JOINで結合します。

 最終結果。

 該当レコードが抽出できました。

○相関サブクエリの例

 さて、上記の方法でも目的の結果が得られますが、別のやり方もあります。

SELECT A.日付,A.担当,A.金額
FROM T実績 AS A
WHERE A.金額=
( SELECT MAX(B.金額)
FROM T実績 AS B
WHERE B.日付 = A.日付 )

 こういう書き方です。

 親のクエリのWHERE条件に、サブクエリを使っているところは、前回ケースのSQLに似ています。
 しかし、サブクエリに、「WHERE A.日付 = B.日付」という、条件があります。
 このようなサブクエリは、相関サブクエリと言うらしいです。

 このSQLがどのように処理されるか、順を追って説明します。
 まず最初に、親クエリのテーブルから、1件レコードが取り出され、評価されます。
 テーブルの1件目、「2012/01/01・A・990」のレコードが取り出されたとします。

 このレコード内容に対して、サブクエリが実行されます。
 具体的には、サブクエリの「A.日付」に、レコードの値が設定された、
SELECT MAX(B.金額)
FROM T実績 AS B
WHERE B.日付 = #2012/01/01#

 が、実行されます。
 2012/01/01の最大金額は、1900ですので、この値がサブクエリの結果になります。

 この結果を元に、親クエリのWHERE条件
WHERE A.金額=
( SELECT MAX(B.金額)
FROM T実績 AS B
WHERE B.日付 = A.日付 )

 は、
WHERE 990=1900
 という内容になります。
 この条件は成立していませんので、1件目のレコードは結果として抽出されません。

 これと同じ事を3件目のデータ、「2012/01/01・C・1900」でやると、
WHERE 1900=1900
 
となり、成立するので、このレコードは結果として抽出されます。

 つまり、相関サブクエリは、親クエリのレコード1件に対して、サブクエリが1回実行されます。

 全レコードの処理イメージを表にすると、以下のような感じです。

 イコールが成り立ったレコードが、結果に抽出される、といった具合です。

 相関サブクエリは、親クエリから1件ずつ処理される、と言う事を念頭に置いて、レコードのデータを当てはめながら処理を追ってみると、分かり易いと思います。


nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

※ブログオーナーが承認したコメントのみ表示されます。
※URL(リンク)は記述できません。

トラックバック 0

トラックバックの受付は締め切りました

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。