Chcę uruchomić to zapytanie:
SELECT DISTINCT ON (address_id) purchases.address_id, purchases.*
FROM purchases
WHERE purchases.product_id = 1
ORDER BY purchases.purchased_at DESC
Ale pojawia się ten błąd:
PG :: Błąd: BŁĄD: WYBIERZ ODRÓŻNIENIE wyrażeń musi pasować do wyrażeń ORDER BY
Dodanie address_id
jako pierwszego ORDER BY
wyrażenia wycisza błąd, ale tak naprawdę nie chcę dodawać sortowania address_id
. Czy można to zrobić bez zamówienia przez address_id
?
sql
postgresql
sql-order-by
distinct-on
sl_bug
źródło
źródło
Odpowiedzi:
Dokumentacja mówi:
Oficjalna dokumentacja
Musisz dodać
address_id
do zamówienia.Alternatywnie, jeśli szukasz pełnego wiersza zawierającego najnowszy zakupiony produkt dla każdego z
address_id
tych wyników i posortowanego wedługpurchased_at
tego, próbujesz rozwiązać największy problem N na grupę, który można rozwiązać za pomocą następujących metod:Ogólne rozwiązanie, które powinno działać w większości DBMS:
Bardziej zorientowane na PostgreSQL rozwiązanie oparte na odpowiedzi @ hkf:
Problem wyjaśniony, rozszerzony i rozwiązany tutaj: wybieranie wierszy uporządkowanych według jednej kolumny i odrębnych w innej
źródło
SELECT DISTINCT ON (purchases.purchased_at, address_id)
. Jednak dwa rekordy o tym samym adresie_id, ale różnych wartościach wartość_zakupu, spowodują duplikaty w zwróconym zestawie. Upewnij się, że znasz dane, o które pytasz.Możesz zamówić według adresu_id w podzapytaniu, a następnie uporządkować według tego, co chcesz w zapytaniu zewnętrznym.
źródło
select
, nie sądzę, że jest to kod produkcyjny?address_id
dwukrotnie (bez potrzeby). Wielu klientów ma problemy ze zduplikowanymi nazwami kolumn.ORDER BY address_id DESC
jest bezcelowe i mylące. Nie robi nic przydatnego w tym zapytaniu. Wynikiem jest dowolny wybór z każdego zestawu wierszy z tym samymaddress_id
, a nie wiersz z najnowszympurchased_at
. Niejednoznaczne pytanie nie wymagało tego wprost, ale prawie na pewno intencja PO. W skrócie: nie używaj tego zapytania . Zamieściłem alternatywy z wyjaśnieniem.Podzapytanie może go rozwiązać:
Wyrażenia wiodące
ORDER BY
muszą zgadzać się z kolumnami wDISTINCT ON
, więc nie można uporządkować według różnych kolumn w tym samymSELECT
.Użyj dodatkowego
ORDER BY
w podzapytaniu tylko wtedy, gdy chcesz wybrać konkretny wiersz z każdego zestawu:Jeśli
purchased_at
możeszNULL
, zastanów sięDESC NULLS LAST
. Pamiętaj jednak, aby dopasować swój indeks, jeśli zamierzasz go używać. Widzieć:Powiązane, z dodatkowymi wyjaśnieniami:
źródło
DISTINCT ON
bez dopasowaniaORDER BY
. Pierwsze zapytanie wymagaORDER BY address_id
wewnętrznego podzapytania.DISTINCT ON
bezORDER BY
w tym samym zapytaniu. Otrzymujesz dowolny wiersz z każdego zestawu elementów równorzędnych zdefiniowanychDISTINCT ON
w tym przypadku w klauzuli. Wypróbuj lub skorzystaj z linków powyżej, aby uzyskać szczegółowe informacje i linki do instrukcji.ORDER BY
w tym samym zapytaniu (tym samymSELECT
) po prostu nie może się nie zgodzićDISTINCT ON
. Też to wyjaśniłem.ORDER BY
jest używana” w dokumentach, ponieważ nie ma dla mnie sensu, aby ta funkcja została zaimplementowana w celu radzenia sobie z niesekwencyjnymi zestawami wartości… a jednak nie pozwoli ci wykorzystaj to z wyraźnym uporządkowaniem. Denerwujący.DISTINCT ON
wyrażeń (jeszcze).Funkcja okna może rozwiązać to w jednym przebiegu:
źródło
address_id
. Zasada może jednak zadziałać. Powiązane przykłady: stackoverflow.com/a/22064571/939860 lub stackoverflow.com/a/11533808/939860 . Istnieją jednak krótsze i / lub szybsze zapytania dotyczące danego problemu.Dla każdego używającego Flask-SQLAlchemy, to zadziałało dla mnie
źródło
query.distinct(foo).from_self().order(bar)
Purchases.query
?Możesz to również zrobić za pomocą klauzuli group by
źródło
purchases
ma tylko dwie kolumnyaddress_id
ipurchased_at
). Z tego powoduGROUP BY
musisz użyć funkcji agregującej, aby uzyskać wartość każdej kolumny nieużywanej do grupowania, więc wszystkie wartości będą pochodzić z różnych wierszy grupy, chyba że przejdziesz przez brzydką i nieefektywną gimnastykę. Można to naprawić tylko przy użyciu funkcji okna, a nieGROUP BY
.