sql >> Database teknologi >  >> RDS >> Oracle

Hent rækken, som har Max-værdien for en kolonne

Jeg ser mange mennesker bruger underforespørgsler eller vinduesfunktioner til at gøre dette, men jeg laver ofte denne form for forespørgsel uden underforespørgsler på følgende måde. Det bruger almindelig standard SQL, så det burde fungere i ethvert mærke af RDBMS.

SELECT t1.*
FROM mytable t1
  LEFT OUTER JOIN mytable t2
    ON (t1.UserId = t2.UserId AND t1."Date" < t2."Date")
WHERE t2.UserId IS NULL;
 

Med andre ord:hent rækken fra t1 hvor der ikke findes en anden række med samme UserId og en større dato.

(Jeg sætter identifikatoren "Dato" i skilletegn, fordi det er et reserveret SQL-ord.)

I tilfælde af, at t1."Date" = t2."Date" , vises fordobling. Normalt har tabeller auto_inc(seq) nøgle, f.eks. id .For at undgå fordobling kan bruges følgende:

SELECT t1.* FROM mytable t1 LEFT OUTER JOIN mytable t2 ON t1.UserId = t2.UserId AND ((t1."Date" < t2."Date") OR (t1."Date" = t2."Date" AND t1.id < t2.id)) WHERE t2.UserId IS NULL;

Re kommentar fra @Farhan:

Her er en mere detaljeret forklaring:

En ydre joinforbindelse forsøger at tilslutte sig t1 med t2 . Som standard er alle resultater af t1 returneres, og hvis der er et match i t2 , er det også returneret. Hvis der ikke er noget match i t2 for en given række af t1 , så returnerer forespørgslen stadig rækken af ​​t1 , og bruger NULL som en pladsholder for alle t2 's kolonner. Sådan fungerer udvendige samlinger generelt.

Tricket i denne forespørgsel er at designe sammenkædningens matchende tilstand, således at t2 skal matche samme userid , og en større date . Ideen er, om der findes en række i t2 der har en større date , derefter rækken i t1 det sammenlignes med kan ikke være den største date for det userid . Men hvis der ikke er nogen match -- dvs. hvis der ikke findes en række i t2 med en større date end rækken i t1 -- vi ved, at rækken i t1 var rækken med den største date for det givne userid .

I disse tilfælde (når der ikke er noget match), kolonnerne i t2 vil være NULL -- selv de kolonner, der er angivet i forbindelsesbetingelsen. Så det er derfor, vi bruger WHERE t2.UserId IS NULL , fordi vi søger efter de tilfælde, hvor der ikke blev fundet en række med en større date for det givne userid .



  1. Sådan afslutter du PostgreSQL kommandolinjeværktøj:psql

  2. Oracle Kombiner flere kolonner til én

  3. Identitetsstigningen hopper i SQL Server-databasen

  4. Django+Postgres:aktuelle transaktion afbrydes, kommandoer ignoreret indtil slutningen af ​​transaktionsblok