Íme két táblázat.
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
SZEMÉLYEK
PERSON_ID + NAME ================= 111222 ABC 222111 XYZ
Itt van az orákulum lekérdezésem.
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;
ami ezt eredményezi
LAST_UPDATE SCHOOL_CODE PERSON_ID ===========+===========+========= 24-JAN-13 ABE 111222 09-FEB-12 ABE 222111
Szeretném kiválasztani az elsőt annak az iskolának, amelynek a legutóbbi dátuma van.
Köszönöm.
Válasz
Az aktuális lekérdezés nem adja meg a kívánt eredményt, mert egy GROUP BY
záradék a PERSON_ID
oszlopban, amelynek mindkét bejegyzéshez egyedi értéke van. Ennek eredményeként mindkét sort visszaadja.
Néhány módon megoldhatja ezt. Allekérdezéssel alkalmazhatja az összesítő függvényt a max(LAST_UPDATE_DATE_TIME)
visszaadásához minden SCHOOL_CODE
esetén:
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;
Lásd: SQL Fiddle demóval
Vagy használhat egy ablakfüggvény a legfrissebb LAST_UPDATE_DATE_TIME
összes iskola adatsorainak visszaadásához:
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;
Lásd: SQL Fiddle with Demo
Ez a lekérdezés megvalósítja a row_number()
, amely egyedi számot rendel a SCHOOL_CODE
partíció minden sorához, és a LAST_UPDATE_DATE_TIME
.
Megjegyzendő, hogy az összesített függvényű JOIN nem pontosan ugyanaz, mint a row_number()
verzió. Ha két sorod van azonos eseményidővel, akkor a JOIN visszaadja mindkét sort, míg a row_number()
csak egyet. Ha mindkettőt vissza szeretné adni egy ablakfüggvénnyel, akkor fontolja meg a rank()
ablakfunkció használatát, mivel az viszonyt ad vissza:
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;
Lásd: Demo
Megjegyzések
- Köszönöm, megtalálom az allekérdező tábla belső illesztése (a fenti 1. példa), hogy a leg intuitívabb legyen .. és nem szükséges, hogy ' megköveteljem, hogy megtanuljam, mi az a partíció a ról ről. Íme egy pillantás az 1. példához hasonló szintaxisra: válassza az oT.dateField, oT.siteID, oT.field1, oT.field2, oT.field3 elemet az originalTable értékéből oT belső csatlakozás (válasszuk a max (dateField) -et legfrissebbDate-ként, siteID-t az originalTable-csoportból siteID szerint) newTable -ként az oT.siteID = newTable.site_ID és oT.dateField = newTable.newestDate sorrendben, amelyet oT.siteID asc talál nekem. Ez jobban megmagyarázza, mi ' s az allekérdezésben történik.
Válasz
I “Meglepődtem, hogy senki sem használta ki a sorszámon () túlmutató ablakfunkciók előnyeit.
Íme néhány adat, amellyel játszani lehet:
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");
Az OVER () záradék egy ablakot hoz létre, amelyhez megadja az összesített csoportokat. Ebben az esetben csak a SHOOL_CODE partíción vagyok, így látni fogjuk a FIRST_VALUE értéket, amely LAST_UPDATE_DATE_TIME-től fog származni, SCHOOL_CODE szerint csoportosítva és LAST_UPDATE_DATE_TIME sorrendben csökkenő sorrendben. Ez az érték minden SCHOOL_CODE oszlopra vonatkozik.
Fontos, hogy fokozott figyelmet fordítson a particionálásra és az over () záradékban történő megrendelésre.
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
Visszaad:
24-JAN-13 ABE 111222
Ezzel feleslegessé válik a GROUP BY és az Subqueries igénye javarészt. Mindenképpen ügyeljen arra, hogy a DISTINCT szerepeljen.
Megjegyzések
- Ez nagyon jó, de van-e mód arra, hogy ne ismételjük a minden oszlop?
Válasz
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)
Megjegyzések
- A just kód feltöltése helyett meg kell próbálnia elmagyarázni, hogy ez hogyan válaszolja meg a kérdést; és potenciálisan azt, amit az OP helytelenül csinált.