最大日付または最新日付のどちらかを選択します

ここに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_CODEmax(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; 

SQL Fiddle with Demo

を参照するか、ウィンドウ関数。最新の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; 

デモ付きSQLフィドル

を参照

このクエリは <を実装しますdiv id = "b132cdda2c">

は、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 内部結合(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が間違って行っていたこと。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です