How to fetch distinct values with arel/relational algebra and has_many :through

匿名 (未验证) 提交于 2019-12-03 08:57:35

问题:

When I try to display all movies that a person is in, and they have more than 1 role (director,writer,actor) in a movie, I get multiple lines for that movie. If I add .select('DISTINCT id') or movies.* to try and eliminate the dups I get the following error:

Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DISTINCT id FROM movies INNER JOIN movie_people ON movies.id = movie_peop' at line 1: SELECTmovies.*, DISTINCT id FROMmoviesINNER JOINmovie_peopleONmovies.id =movie_people.movie_id WHERE ((movie_people`.person_id = 601619)) ORDER BY title LIMIT 18 OFFSET 0

I don't know how to code the arel request correctly. Please help.
Thank you.

app/controllers

class PeopleController < ApplicationController   def show       @person = Person.find(params[:id])       @movies = @person.movies.select('DISTINCT id').       paginate :per_page => 18, :page => params[:page],                :order => sort_order(params[:sort])  end   

app/models

class Person < ActiveRecord::Base     has_many :movie_people     has_many :movies, :through => :movie_people   end    class MoviePerson < ActiveRecord::Base     belongs_to :movie     belongs_to :person   end    class Movie < ActiveRecord::Base     has_many :movie_people     has_many :people, :through => :movie_people   end   

db/schema.rb

  create_table "people", :force => true do |t|       t.string   "name"     end      create_table "movie_people", :force => true do |t|       t.integer  "movie_id"       t.integer  "person_id"       t.integer  "role"     end      create_table "movies", :force => true do |t|       t.string   "title"       t.string   "year"     end   

movies/show.html.erb

Title:<%= @movie.title %><br> Year:<%= @movie.year %><br> <% @movie.movie_people.group_by(&:role).each do |r, a| %>    <%= %w(Director: Writer: Cast:)[r] %>     <% a.each do |c| %>      <%= link_to c.person.name,         :controller => 'people', :action => 'show', :id => c.person.id %>   <% end %><br>   <% end %>   

Title: Fahrenheit 9/11
Year: 2004
Director: Michael Moore
Writer: Michael Moore
Cast: Michael Moore George W. Bush

people/show.html.erb

Name:<%= @person.name %> <% @movies.each do |movie| %>   <br><%= link_to movie.title, movie %> (<%= movie.year %>)   <% end %>   

Name: Michael Moore
Fahrenheit 9/11 (2004)
Fahrenheit 9/11 (2004)
Fahrenheit 9/11 (2004)

回答1:

In Arel, uniq generates the appropriate select distinct SQL. I'm not sure how to add Arel to a has_many association, but in regular (controller) code it would be something like

@person.movies.uniq 

See http://apidock.com/rails/ActiveRecord/QueryMethods/uniq and Rails Arel selecting distinct columns



回答2:

This is probably a bug with Rails.

In the meantime, you can exclude the select before select distinct, like so:

@person.movies.except(:select).select('DISTINCT id') 


回答3:

This solved my problem - rails - using :select(distinct) with :has_many :through association produces invalid SQL

has_many :movies, :through => :movie_people, :select => 'distinct movies.*' 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!