Ich habe kein Oracle, um es zu testen, aber die effizienteste Lösung ist die Verwendung analytischer Abfragen. Sie sollte etwa so aussehen:
SELECT DISTINCT
UserId
, MaxValue
FROM (
SELECT UserId
, FIRST (Value) Over (
PARTITION BY UserId
ORDER BY Date DESC
) MaxValue
FROM SomeTable
)
Ich vermute, dass Sie die äußere Abfrage loswerden und die innere Abfrage unterscheiden können, aber ich bin mir nicht sicher. In der Zwischenzeit weiß ich, dass dies funktioniert.
Wenn Sie mehr über analytische Abfragen erfahren möchten, empfehle ich Ihnen die Lektüre http://www.orafaq.com/node/55 y http://www.akadia.com/services/ora_analytic_functions.html . Hier ist die kurze Zusammenfassung.
Unter der Haube sortieren analytische Abfragen den gesamten Datensatz und verarbeiten ihn dann sequentiell. Bei der Verarbeitung partitionieren Sie den Datensatz nach bestimmten Kriterien und betrachten dann für jede Zeile ein Fenster (standardmäßig den ersten Wert in der Partition der aktuellen Zeile - dieser Standardwert ist auch der effizienteste) und können Werte mithilfe einer Reihe von analytischen Funktionen berechnen (die Liste der Funktionen ist den Aggregatfunktionen sehr ähnlich).
In diesem Fall wird die innere Abfrage folgendermaßen durchgeführt. Der gesamte Datensatz wird nach UserId und dann nach Datum DESC sortiert. Dann wird er in einem Durchgang verarbeitet. Für jede Zeile geben Sie die UserId und das erste Datum zurück, das für diese UserId gesehen wurde (da die Daten DESC sortiert sind, ist das das maximale Datum). So erhalten Sie Ihre Antwort mit doppelten Zeilen. Die äußere DISTINCT zerdrückt dann die Duplikate.
Dies ist kein besonders spektakuläres Beispiel für analytische Abfragen. Ein weitaus größerer Gewinn wäre es, wenn Sie eine Tabelle mit Finanzeinnahmen nehmen und für jeden Benutzer und jede Einnahme eine laufende Gesamtsumme dessen berechnen, was er bezahlt hat. Analytische Abfragen lösen das effizient. Andere Lösungen sind weniger effizient. Deshalb sind sie auch Teil des SQL-Standards 2003. (Leider hat Postgres sie noch nicht. Grrr...)