2012-03-18 19 views
14

Mam następujące zapytanie:Rails 3, ActiveRecord, PostgreSQL - polecenie ".uniq" nie działa?

Article.joins(:themes => [:users]).where(["articles.user_id != ?", current_user.id]).order("Random()").limit(15).uniq 

i daje mi błąd

PG::Error: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list 
LINE 1: ...s"."user_id" WHERE (articles.user_id != 1) ORDER BY Random() L... 

Kiedy zaktualizować oryginalny kwerendy

Article.joins(:themes => [:users]).where(["articles.user_id != ?", current_user.id]).order("Random()").limit(15)#.uniq 

więc błąd nie ma ... W MySQL .uniq działa, w PostgreSQL nie. Czy istnieje jakaś alternatywa?

+0

Czy na pewno zapytanie z 'unikq' zwraca inny wynik? Pokaż rzeczywiste zapytania SQL dla każdego wariantu (użyj metody 'sql'). – taro

+0

Jestem pewien. Kiedy użyłem tego zapytania z bazą danych MySQL, więc bez '.uniq' zwrócił mi również ten sam wiersz, ale z' .uniq' zawsze unikalny wiersz. W PostgreSQL, jeśli używam '.uniq', otrzymuję błąd określony powyżej, jeśli nie używam' .uniq', więc błąd zniknął, ale otrzymuję również te same wiersze z DB. – user984621

Odpowiedz

30

Jako błąd podaje for SELECT DISTINCT, ORDER BY expressions must appear in select list. Dlatego musisz wyraźnie wybrać klauzulę, którą zamawiasz.

Oto przykład, jest podobny do twojego przypadku, ale trochę uogólniaj.

Article.select('articles.*, RANDOM()') 
     .joins(:users) 
     .where(:column => 'whatever') 
     .order('Random()') 
     .uniq 
     .limit(15) 

więc wyraźnie zawierać klauzulę ORDER BY (w tym przypadku RANDOM()) używając .select(). Jak pokazano powyżej, aby zapytanie zwróciło atrybuty artykułu, musisz je jawnie zaznaczyć.

Mam nadzieję, że to pomoże; powodzenia

+2

Dlaczego musisz nawet dodać to, co zamawiasz, do klauzuli select na pierwszym miejscu w postgresql. Jeśli używasz join, to sql powinien być wystarczająco inteligentny, aby wiedzieć, co zamówić przez bez jawnie deklarując go w klauzuli select (zwłaszcza, że ​​klauzula select ma na celu ograniczenie zwróconych kolumn). – JohnMerlino

+0

Czy włączenie 'RANDOM()' całkowicie nie neguje 'DISTINCT', ponieważ bierze pod uwagę zestaw całkowicie unikalnych wartości? I jako taki kończysz z duplikatami rekordów tak, jakbyś nie używał "DISTINCT" w pierwszej kolejności? –

1

Zakładam, że metoda .uniq jest tłumaczona na klauzulę DISTINCT w SQL. PostgreSQL jest wybredny (większy niż MySQL) - wszystkie pola na liście wyboru podczas używania DISTINCT muszą być obecne w klauzulach ORDER_BY (i GROUP_BY).

To trochę niejasne, co próbujesz zrobić (losowe zamówienie?). Oprócz wysłania pełnego wysłanego kodu SQL, jeśli mógłbyś wyjaśnić swój cel, może to być pomocne w znalezieniu alternatywy.

+0

Prawdopodobnie masz rację, ale istnieje jakiś elegancki sposób na integrację z zapytaniem powyżej "DISTINCT" clausule? Moje obecne zapytanie jest "dość krótkie", mogę użyć 'find_by_sql' i tam prosto do ustawienia clausule' DISTINCT', ale w tym przypadku zapytanie będzie o wiele większe. – user984621

0

Właśnie zaktualizowałem moją 100% działającą i przetestowaną aplikację z 3.1.1 do 3.2.7 i mam teraz ten sam PG :: Błąd.

Używam Cancan ...

@users = User.accessible_by (current_ability) .order ('lname mal'). Uniq

Zdejmowanie .uniq rozwiązuje ten problem i nie było konieczne tak czy inaczej dla tego prostego zapytania.

Wciąż przeglądając notatki zmian między 3.1.1 a 3.2.7, aby zobaczyć, co spowodowało, że to pęknie.

2

Aby wzbogacić wątek o więcej przykładów, na wypadek, gdyby w zapytaniu były relacje zagnieżdżone, możesz wypróbować następującą instrukcję.

Person.find(params[:id]).cars.select('cars.*, lower(cars.name)').order("lower(cars.name) ASC") 

W podanym przykładzie, pytasz wszystkie samochody dla danej osoby, na zlecenie (nazwa modelu Audi, Ferrari, Porsche)

nie sądzę, że jest to lepszy sposób, ale może pomóc rozwiązać ten rodzaj myślenia w obiektach i kolekcjach, zamiast w sposób relacyjny (baza danych).

Dzięki!

Powiązane problemy