sql >> Databasteknik >  >> RDS >> Oracle

Hämta raden som har maxvärdet för en kolumn

Jag ser att många använder subqueries eller fönsterfunktioner för att göra detta, men jag gör ofta den här typen av fråga utan subqueries på följande sätt. Den använder vanlig, standard SQL så den borde fungera i alla märken av 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 andra ord:hämta raden från t1 där ingen annan rad finns med samma UserId och ett större datum.

(Jag sätter identifieraren "Datum" i avgränsare eftersom det är ett reserverat SQL-ord.)

I fallet om t1."Date" = t2."Date" , visas en fördubbling. Vanligtvis har tabeller auto_inc(seq) nyckel, t.ex. id .För att undvika fördubbling kan användas följande:

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;

Om kommentar från @Farhan:

Här är en mer detaljerad förklaring:

En yttre koppling försöker ansluta till t1 med t2 . Som standard är alla resultat av t1 returneras och om det finns en matchning i t2 , den återlämnas också. Om det inte finns någon matchning i t2 för en given rad med t1 , då returnerar frågan fortfarande raden t1 , och använder NULL som platshållare för alla t2 s kolumner. Det är bara så ytterskarvar fungerar i allmänhet.

Tricket i den här frågan är att utforma kopplingens matchningsvillkor så att t2 måste matcha samma userid och en större date . Tanken är om det finns en rad i t2 som har ett större date , sedan raden i t1 det jämförs med kan inte vara det största date för det userid . Men om det inte finns någon matchning -- dvs om det inte finns någon rad i t2 med ett större date än raden i t1 -- vi vet att raden i t1 var raden med störst date för det givna userid .

I de fallen (när det inte finns någon matchning), kolumnerna i t2 kommer att vara NULL -- även de kolumner som anges i kopplingsvillkoret. Så det är därför vi använder WHERE t2.UserId IS NULL , eftersom vi söker efter fall där ingen rad hittades med ett större date för det givna userid .



  1. Hur UNION fungerar i PostgreSQL

  2. Hur man använder parameter med LIKE i SQL Server Compact Edition

  3. Din ultimata guide till SQL Joins:OUTER JOIN – Del 2

  4. Fråga efter data genom att sammanfoga två tabeller i två databaser på olika servrar