# 最大日付と最新日付のどちらを選択する

15

``````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``````

これが私のoracleクエリです。

``````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``````

ありがとう。

28

これを解決する方法はいくつかあります。サブクエリを使用して、集約関数を適用して`max(LAST_UPDATE_DATE_TIME)`for each を返すことができます`SCHOOL_CODE`

``````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 Fiddle with Demoをご覧ください

このクエリ`row_number()`は、のパーティション内の各行に一意の番号を割り当て、に`SCHOOL_CODE`基づいて降順で配置し`LAST_UPDATE_DATE_TIME`ます。

``````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;``````

デモを見る

4

``````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でのみパーティション分割しているため、FIRST_VALUEが表示されます。これは、LAST_UPDATE_DATE_TIMEから取得され、SCHOOL_CODEでグループ化され、降順でLAST_UPDATE_DATE_TIMEの順になります。この値は、各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``

これにより、ほとんどの場合、GROUP BYおよびサブクエリが不要になります。ただし、DISTINCTを含めるようにしてください。

1
``````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)``````

1
コードだけを投稿するのではなく、これが質問にどのように答えるかを説明してください。そして潜在的にOPが間違っていたこと。
マックスヴァーノン