Sorting by joined table value with Rails - ruby-on-rails

I'm trying to sort a list of items based on the value of field on a joined table. Here's what I've got so far:
FeaturedEvent.joins(:event).order('event.start_datetime').limit(5)
This looks right to me but when it's run it returns a Postgres error about there being a missing FROM statement:
PG::UndefinedTable: ERROR: missing FROM-clause entry for table "event" LINE 1: ...ts"."id" = "featured_events"."event_id" ORDER BY event.star... ^ : SELECT "featured_events".* FROM "featured_events" INNER JOIN "events" ON "events"."id" = "featured_events"."event_id" ORDER BY event.start_datetime LIMIT 5
I tried the suggestions in this post about putting the ordering in default scope but it came out with the same error – I'm guessing it's a Postgres thing.
How can I fix this?
Thanks!

Try
FeaturedEvent.includes(:event).order('events.start_datetime').limit(5)
In your order the table name should be the real database table name.
As I guess, the table name must be events

Your table name is events so you just have to add s in event
FeaturedEvent.joins(:event).order('events.start_datetime').limit(5)

Related

Rails group by query still return duplicate record

i've some query to select all data based on skipped_play_id but when i'm execute the query it still return some duplicate skipped_play_id
user = User.first
skipped_plays=user.user_skipped_plays.select(:skipped_play_id,:created_at).group(:created_at,:skipped_play_id)
and why should i provide :created_at as one of group by argument if i only need query grouped by skipped_play_id. if i change my query to user.user_skipped_plays.select(:skipped_play_id,:created_at).group(:skipped_play_id)
it will return
ActiveRecord::StatementInvalid: PG::GroupingError: ERROR: column "user_skipped_plays.created_at" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT "user_skipped_plays"."skipped_play_id", "user_skippe...
^
: SELECT "user_skipped_plays"."skipped_play_id", "user_skipped_plays"."created_at" FROM "user_skipped_plays" WHERE "user_skipped_plays"."user_id" = $1 GROUP BY "user_skipped_plays"."skipped_play_id" ORDER BY "user_skipped_plays"."id" ASC LIMIT $2
from /Users/fourtyonestudio/.rvm/gems/ruby-2.3.1/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/postgresql_adapter.rb:657:in `prepare
i'll really appreciate any advice
I think you don't need GROUP BY in your code at all. If you need to select unique rows containing just skipped_play_id and created_at you can go with:
user.user_skipped_plays.select(:skipped_play_id, :created_at).uniq
But in such selection you will still get duplicated skipped_play_id if you have different rows with same skipped_play_id, but different created_at, because you take a combination. So, possibly, you just need to go with:
user.user_skipped_plays.select(:skipped_play_id).uniq
It depends on what you need. You can type in comments for my answer how do you plan to use this selection and I will help you to solve your issue
Please try this
User.first.user_skipped_plays.group_by { |t| t.skipped_play_id }
Let me know if you are getting correct data or not

Order by Position Error

We have created a query on Rails with Postgres database, where we want courses to be in order by position as data available in an array, in our case it is course_ids.
A course_ids array contains courses' ids in squences.
Course.includes(:course_series).
where("course_id IN (?)", course_ids).
order("position(course_id::text in '?')", course_ids.join(',')).
order('course_name asc')
but it showing below error
ActiveRecord::StatementInvalid in FrontendController#get_courses
PG::InvalidColumnReference: ERROR: ORDER BY position 52 is not in select list
LINE 1: ...9)) ORDER BY position(course_id::text in '?'), 11,52, course...
^
: SELECT "at_courses".* FROM "at_courses" WHERE "at_courses"."deleted_at" IS NULL AND (course_id IN (52,11)) ORDER BY position(course_id::text in '?'), 52,11, course_name asc
Extracted source (around line #598):
Could you please share what went wrong here? Please go easy on me. I am not a technical guy.
Thanks!

PostgreSQL ActiveRecord::StatementInvalid: PG::GroupingError: ERROR: must appear in the GROUP BY

I have got difficulties group in PostGreSQL. My code below
Invoice.select("customer_id, due_date, sum(balance) AS total_balance, total_mount").group(:customer_id)
I have got the errors
Invoice Load (1.8ms) SELECT customer_id, due_date, sum(balance) AS total_balance, total_amount FROM "records" WHERE "records"."type" IN ('Invoice') GROUP BY "records"."customer_id"
ActiveRecord::StatementInvalid: PG::GroupingError: ERROR: column "records.due_date" must appear in the GROUP BY clause or be used in an aggregate function
enter code here
LINE 1: SELECT customer_id, due_date, sum(balance) AS total_balance,...
UPDATE
Thanks for #slicedpan for the solution. I have update like below code.
Invoice.select("customer_id, MAX(due_date), SUM(balance) AS total_balance").group(:customer_id)
I have read many of articles about that but It still show the error.
This error is due to the fact that Postgres doesn't know what to do with the due_date column. The query you have written is basically:
for each customer, show me the total sum of the balances for all their invoices, and the due date for one of their invoices.
The problem here is that in PostgreSQL you have to be explicit about which invoice you want to show the due_date of, whereas in MySQL or SQLite it will pick one (can't remember how off the top of my head). In this case I think it would make more sense to leave out the due_date from the select, otherwise use MAX(due_date) to get the most recent, or something like that.
You can get the same functionality as MySQL/SQLite if you do it like this:
Invoice.select("DISTINCT ON (customer_id) customer_id, due_date, sum(balance) over(partition by customer_id) AS total_balance, total_mount")
It will sum balance and select "random" due_date/total_mount for each customer_id. Just like non-standard GROUP BY possible in those 2 other RDBMS.

How to select attribute that is method?

Maybe a question is little confusing but I will explain.
I wrote a query to select some data and I need to select title but title isn't column in table it is method in model (combined from two fields). How I can in query use that title method? I tried some things but it keeps telling me that title field is missing.
Concert.select('entity_changes.updated_at, concerts.id, concerts.title').joins('left join entity_changes on entity_changes.id = concerts.id')
.where(:clazz_name => 'Concert').order('entity_changes.updated_at DESC').limit(5)
and I get this error
ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR: column "title" does not exist

Postgresql and rails with act-as-taggable-on error

I have this statement to choose a given number of random records from the database that match certain set of tags. I am using act-as-taggable-on gem for tagging.
questions=Question.select('questions.*,RANDOM()').tagged_with(tags,:any=>true).order("RANDOM()").limit(test.no_of_questions)
I am using postgresql and I get the following error.
PG::Error: ERROR: syntax error at or near "DISTINCT"
LINE 1: SELECT questions.*,RANDOM(), DISTINCT questions.* FROM "que...
^
: SELECT questions.*,RANDOM(), DISTINCT questions.* FROM "questions" JOIN taggings quest_taggings_14e6dd0 ON quest_taggings_14e6dd0.taggable_id = "questions".id AND quest_taggings_14e6dd0.taggable_type = 'Question' WHERE (quest_taggings_14e6dd0.tag_id = 1) ORDER BY RANDOM() LIMIT 3
I am not sure what to do because I think the Distinct part is inserted by the tagging gem.
Thanks in advance!
You can do it along these lines
Question.tagged_with(tags,:any=>"true").order("RANDOM()").limit(limit_number)
update
As shown here http://archives.postgresql.org/pgsql-sql/2010-10/msg00004.php
You need to put the DISTINCT and the ORDER BY in separate query levels.
Apparently, the above Query would work with other DB but not Postgresql
Nevermind Ive found the solution.
I did this:
questions=Question.tagged_with(tags,:any=>true)
questions=questions.select('questions.*,RANDOM()').order("RANDOM()").limit(test.no_of_questions)
This way the questions.* wasnt included twice in the select statement.

Resources