ここに2つのテーブルがあります。
SCHOOL_STAFF
SCHOOL_CODE + STAFF_TYPE_NAME + LAST_UPDATE_DATE_TIME + PERSON_ID ================================================================= ABE Principal 24-JAN-13 111222 ABE Principal 09-FEB-12 222111
担当者
PERSON_ID + NAME ================= 111222 ABC 222111 XYZ
これが私のオラクルクエリです。
SELECT MAX(LAST_UPDATE_DATE_TIME) AS LAST_UPDATE, SCHOOL_CODE, PERSON_ID FROM SCHOOL_STAFF WHERE STAFF_TYPE_NAME="Principal" GROUP BY SCHOOL_CODE, PERSON_ID ORDER BY SCHOOL_CODE;
この結果が得られます
LAST_UPDATE SCHOOL_CODE PERSON_ID ===========+===========+========= 24-JAN-13 ABE 111222 09-FEB-12 ABE 222111
最新の日付の学校の最初のものを選択したいと思います。
ありがとうございます。
回答
GROUP BY
<を使用しているため、現在のクエリでは目的の結果が得られません。 PERSON_ID
列の/ div>句。両方のエントリに一意の値があります。その結果、両方の行が返されます。
これを解決する方法はいくつかあります。サブクエリを使用して集計関数を適用し、各SCHOOL_CODE
のmax(LAST_UPDATE_DATE_TIME)
を返すことができます。
select s1.LAST_UPDATE_DATE_TIME, s1.SCHOOL_CODE, s1.PERSON_ID from SCHOOL_STAFF s1 inner join ( select max(LAST_UPDATE_DATE_TIME) LAST_UPDATE_DATE_TIME, SCHOOL_CODE from SCHOOL_STAFF group by SCHOOL_CODE ) s2 on s1.SCHOOL_CODE = s2.SCHOOL_CODE and s1.LAST_UPDATE_DATE_TIME = s2.LAST_UPDATE_DATE_TIME;
を参照するか、ウィンドウ関数。最新のLAST_UPDATE_DATE_TIME
を含む各学校のデータ行を返します:
select SCHOOL_CODE, PERSON_ID, LAST_UPDATE_DATE_TIME from ( select SCHOOL_CODE, PERSON_ID, LAST_UPDATE_DATE_TIME, row_number() over(partition by SCHOOL_CODE order by LAST_UPDATE_DATE_TIME desc) seq from SCHOOL_STAFF where STAFF_TYPE_NAME="Principal" ) d where seq = 1;
を参照
は、SCHOOL_CODE
のパーティションの各行に一意の番号を割り当て、
。
補足として、集計関数を使用したJOINは、row_number()
バージョンとまったく同じではありません。同じイベント時間の2つの行がある場合、JOINは両方の行を返しますが、row_number()
は1つだけを返します。ウィンドウ関数で両方を返したい場合は、代わりにrank()
ウィンドウ関数を使用することを検討してください。タイが返されます:
select SCHOOL_CODE, PERSON_ID, LAST_UPDATE_DATE_TIME from ( select SCHOOL_CODE, PERSON_ID, LAST_UPDATE_DATE_TIME, rank() over(partition by SCHOOL_CODE order by LAST_UPDATE_DATE_TIME desc) seq from SCHOOL_STAFF where STAFF_TYPE_NAME="Principal" ) d where seq = 1;
コメント
- ありがとうございます。サブクエリテーブルへの内部結合(上記の例1)が最も直感的であり、' パーティションがすべてであるかを学習する必要はありません。約。例1と同様の構文を次に示します。 originalTable から oT bとしてoT.dateField、oT.siteID、oT.field1、oT.field2、oT.field3を選択します。 >内部結合(select max(dateField)as newestDate、siteID from originalTable group by siteID)as newTable on oT.siteID = newTable.site_ID and oT.dateField = newTable.newestDate order by oT.siteID asc私にとって、それは何をよりよく説明しています'がサブクエリで発生しています。
回答
I 「row_number()以外のウィンドウ関数を利用した人がいないことに驚いています
以下のデータを試してみてください:
CREATE TABLE SCHOOL_STAFF ( LAST_UPDATE_DATE_TIME VARCHAR(20), SCHOOL_CODE VARCHAR(20), PERSON_ID VARCHAR(20), STAFF_TYPE_NAME VARCHAR(20) ); INSERT INTO SCHOOL_STAFF VALUES ("24-JAN-13", "ABE", "111222", "Principal"); INSERT INTO SCHOOL_STAFF VALUES ("09-FEB-12", "ABE", "222111", "Principal");
OVER()句は、集約グループを定義するためのウィンドウを作成します。この場合、私はSHOOL_CODEでのみパーティションを作成しているため、LAST_UPDATE_DATE_TIMEから取得され、SCHOOL_CODEでグループ化され、LAST_UPDATE_DATE_TIMEの降順でFIRST_VALUEが表示されます。この値は、各SCHOOL_CODEの列全体に適用されます。
over()句でのパーティション分割と順序付けに細心の注意を払うことが重要です。
SELECT DISTINCT FIRST_VALUE(LAST_UPDATE_DATE_TIME) OVER (PARTITION BY SCHOOL_CODE ORDER BY LAST_UPDATE_DATE_TIME DESC) AS LAST_UPDATE ,FIRST_VALUE(SCHOOL_CODE) OVER (PARTITION BY SCHOOL_CODE ORDER BY LAST_UPDATE_DATE_TIME DESC) AS SCHOOL_CODE ,FIRST_VALUE(PERSON_ID) OVER (PARTITION BY SCHOOL_CODE ORDER BY LAST_UPDATE_DATE_TIME DESC) AS PERSON_ID FROM SCHOOL_STAFF WHERE STAFF_TYPE_NAME = "Principal" ORDER BY SCHOOL_CODE
戻り値:
24-JAN-13 ABE 111222
これにより、GROUPBYとサブクエリが不要になります。ほとんどの場合。ただし、必ずDISTINCTを含めることをお勧めします。
コメント
- これは便利ですが、のover句の繰り返しを回避する方法はあります。すべての列?
回答
select LAST_UPDATE_DATE_TIME as LAST_UPDATE, SCHOOL_CODE, PERSON_ID from SCHOOL_STAFF WHERE STAFF_TYPE_NAME="Principal" AND LAST_UPDATE_DATE_TIME = (SELECT MAX(LAST_UPDATE_DATE_TIME) FROM SCHOOL_STAFF s2 WHERE PERSON_ID = s2.PERSON_ID)
コメント
- just コードを投稿する代わりに、これが質問にどのように答えるかを説明するようにしてください。そして潜在的にOPが間違って行っていたこと。