Zapytanie może działać tak:
SELECT a.*
FROM article a
LEFT JOIN (
SELECT DISTINCT ON (article_id)
article_id, value
FROM metrics m
WHERE name = 'score'
ORDER BY article_id, date_created DESC
) m ON m.metrics_id = a.metrics_id
ORDER BY m.value DESC;
Pierwszy , pobierz „najnowszą” value dla name = 'score' na artykuł w podzapytaniu m . Więcej wyjaśnień dotyczących zastosowanej techniki w tej powiązanej odpowiedzi:
Wydaje się jednak, że padasz ofiarą bardzo podstawowego nieporozumienia:
Nie ma nie ma „naturalnego porządku” w tabeli. W SELECT , musisz ORDER BY dobrze zdefiniowane kryteria. Na potrzeby tego zapytania zakładam kolumnę metrics.date_created . Jeśli nie masz nic takiego, nie masz mowy aby zdefiniować "najnowsze" i są zmuszeni powrócić do arbitralnego wyboru z wielu kwalifikujących się wierszy:
ORDER BY article_id
To nie wiarygodny. Postgres wybierze wiersz według własnego uznania. Może ulec zmianie wraz z każdą aktualizacją tabeli lub zmianą planu zapytań.
Dalej , LEFT JOIN do tabeli article i ORDER BY value . NULL sortuje na końcu, więc artykuły bez kwalifikującej się wartości idą na końcu.
Uwaga:niektóre niezbyt inteligentne ORM (a obawiam się, że ActiveRecord Ruby jest jednym z nich) używają nieopisowego i nierozróżnialnego id jako nazwa klucza podstawowego. Musisz dostosować się do rzeczywistych nazw kolumn, których nie podałeś.
Wydajność
Powinno być przyzwoite. To "proste" zapytanie, jeśli chodzi o Postgres. Częściowy indeks wielokolumnowy w tabeli metrics przyspieszyłoby to:
CREATE INDEX metrics_some_name_idx ON metrics(article_id, date_created)
WHERE name = 'score';
Kolumny w tej kolejności. W PostgreSQL 9.2+ możesz dodać wartość kolumny, aby umożliwić skanowanie tylko z indeksem:
CREATE INDEX metrics_some_name_idx ON metrics(article_id, date_created, value)
WHERE name = 'score';