PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Railsy 3.1 z PostgreSQL:GROUP BY muszą być używane w funkcji agregującej

Sql wygenerowany przez wyrażenie nie jest prawidłowym zapytaniem, grupujesz według user_id i wybierając wiele innych pól na tej podstawie, ale nie mówiąc DB, jak powinna agregować inne pola. Na przykład, jeśli Twoje dane wyglądają tak:

a  | b
---|---
1  | 1
1  | 2
2  | 3

Teraz, gdy poprosisz db o pogrupowanie według a a także zwraca b, nie wie, jak agregować wartości 1,2 . Musisz powiedzieć, czy musi wybrać min, max, średnia, suma czy coś innego. Gdy pisałem odpowiedź, pojawiły się dwie odpowiedzi, które mogą to wszystko lepiej wyjaśnić.

Jednak w twoim przypadku użycia myślę, że nie chcesz grupować na poziomie bazy danych. Ponieważ jest tylko 10 sztuk, możesz je pogrupować w swojej aplikacji. Nie używaj tej metody w przypadku tysięcy dzieł sztuki:

 arts = Art.all(:order => "created_at desc", :limit => 10)
 grouped_arts = arts.group_by {|art| art.user_id}
 # now you have a hash with following structure in grouped_arts
 # { 
 #    user_id1 => [art1, art4],
 #    user_id2 => [art3],
 #    user_id3 => [art5],
 #    ....
 # }

EDYTUJ: Wybierz ostatnie_arty, ale tylko jedną sztukę na użytkownika

Żeby dać ci ideę sql (nie testowałem tego, ponieważ nie mam zainstalowanego RDBMS w moim systemie)

SELECT arts.* FROM arts
WHERE (arts.user_id, arts.created_at) IN 
  (SELECT user_id, MAX(created_at) FROM arts
     GROUP BY user_id
     ORDER BY MAX(created_at) DESC
     LIMIT 10)
ORDER BY created_at DESC
LIMIT 10

To rozwiązanie opiera się na praktycznym założeniu, że żadne dwie sztuki dla tego samego użytkownika nie mogą mieć tego samego najwyższego wartości created_at, ale może to być błędne, jeśli importujesz lub programowo tworzysz większość sztuk. Jeśli założenie nie jest prawdziwe, sql może być bardziej zmyślone.

EDYTUJ: Spróbuj zmienić zapytanie na Arel:

Art.where("(arts.user_id, arts.created_at) IN 
             (SELECT user_id, MAX(created_at) FROM arts
                GROUP BY user_id
                ORDER BY MAX(created_at) DESC
                LIMIT 10)").
    order("created_at DESC").
    page(params[:page]).
    per(params[:per])


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Problemy z zapytaniami SQLite3 i Postgres/Heroku Ruby on Rails

  2. Wywołaj getNextException, aby zobaczyć przyczynę:Jak sprawić, by Hibernate / JPA wyświetlał komunikat serwera DB dla wyjątku

  3. Jak usunąć duplikaty w tabeli?

  4. Postgres - jak zaszyfrować kolumnę i jej dane

  5. WYBIERZ z jednej tabeli, WSTAW do dwóch innych tabel na podstawie warunku