I have a table named property_audit_version_histories.
i am fetching the records using the following code
#version_logs = PropertyAuditVersionHistory
.includes(:property_audit_version, :user)
.where(property_audit_version_id: params[:id])
The result contain 3 records, 2 of which have the same action and user_id
Now i need to group the records using the columns action, user_id
I am getting the following error when i try to group the records
#version_logs = PropertyAuditVersionHistory
.includes(:property_audit_version, :user)
.where(property_audit_version_id: params[:id])
.group("action, user_id")
PG::GroupingError: ERROR: column "property_audit_version_histories.id" must appear in the GROUP BY clause or be used in an aggregate function
Based on the thread PG::GroupingError: ERROR: column "events.id" must appear in the GROUP BY clause or be used in an aggregate function i have modified the code as follows
#version_logs = PropertyAuditVersionHistory
.includes(:property_audit_version, :user)
.group("property_audit_version_histories.id")
.where(property_audit_version_id: params[:id])
.group("action, user_id")
Now the error is gone but still the result is having 3 records. After grouping i expect only 2 records.
Any idea on how to fix this?
You cant select all columns like mysql in postgresql when doing aggregrates.
So I guess this should work.
#version_logs = PropertyAuditVersionHistory
.where(property_audit_version_id: params[:id])
.group("action", "user_id", "property_audit_version_id")
.select("user_id", "action", "property_audit_version_id")
I dont know how is your model but this should work. If you need more fields let me know
What you need to do is specify which columns you want with
.select("user_id")
But for the columns you know will be the same use max(columnName) as columnName
for example:
.select("MAX(user_id) as user_id, action")
Make sure you are 100% sure that those columns will be the same value after grouping.
Related
Suppose I have an Employee model, there is a method in Employee model named def fixed
def fixed
return self.cached_fixed.to_f if self.cached_fixed.present?
return (self.current_salary && self.current_salary.fixed).to_f
end
end
def current_salary
return #current_salary if #current_salary
# #current_salary = self.employee_salaries.detect{|es| es.end_date == nil}
#current_salary = self.db_current_salary
return #current_salary
end
if the fixed were a column in employee table we could have just used Employee.distinct.select(:fixed) to pull the distinct values
is there a way if it's just a method not a field in table without loading all the employees.
I am expecting to get the unique values of a column from a table , but it may not be a column as in the above table
Not for an arbitrary method, no. But you start the query from the EmployeeSalary end and fetch only the column you care about in one query using select:
EmployeeSalary
.select(:fixed)
.join(:employee)
.where(end_date: nil)
This will run a select fixed from... query and return a list of EmployeeSalary objects, but all the fields that aren't listed in the select call will be nil. Assuming the constraint of only one salary record having end_date: nil, there will be one EmployeeSalary object per employee. You can add .distinct in the method chain if you want unique values.
I'm not sure how the caching logic fits into this question. You can apply caching logic on top of that list if you like, but doing one query like this is pretty fast.
How do you query on Ruby on Rails or translate this query on Ruby on Rails?
SELECT
orders.item_total,
orders.total,
payments.created_at,
payments.updated_at
FROM
public.payments,
public.orders,
public.line_items,
public.variants
WHERE
payments.order_id = orders.id AND
orders.id = line_items.order_id AND
This is working on Postgres but I'm new to RoR and it's giving me difficulty on querying this sample.
So far this is what I have.
Order.joins(:payments,:line_items,:variants).where(payments:{order_id: [Order.ids]}, orders:{id:LineItem.orders_id}).distinct.pluck(:email, :id, "payments.created_at", "payments.updated_at")
I have a lot of reference before asking a question here are the links.
How to combine two conditions in a where clause?
Rails PG::UndefinedTable: ERROR: missing FROM-clause entry for table
Rails ActiveRecord: Pluck from multiple tables with same column name
ActiveRecord find and only return selected columns
https://guides.rubyonrails.org/v5.2/active_record_querying.html
from all that link I produced this code that works for testing.
Spree::Order.joins(:payments,:line_items,:variants).where(id: [Spree::Payment.ids]).distinct.pluck(:email, :id)
but when I try to have multiple queries and pluck a specific column name from a different table it gives me an error.
Update
So I'm using Ransack to query I produced this code.
#search = Spree::Order.ransack(
orders_gt: params[:q][:created_at_gt],
orders_lt: params[:q][:created_at_lt],
payments_order_id_in: [Spree::Order.ids],
payments_state_eq: 'completed',
orders_id_in: [Spree::LineItem.all.pluck(:order_id)],
variants_id_in: [Spree::LineItem.ids]
)
#payment_report = #search.result
.includes(:payments, :line_items, :variants)
.joins(:line_items, :payments, :variants).select('payments.response_code, orders.number, payments.number')
I don't have error when I remove the select part and I need to get that specific column. Is there a way?
You just have to make a join between the tables and then select the columns you want
Spree::Order.joins(:payments, :line_items).pluck("spree_orders.total, spree_orders.item_total, spree_payments.created_at, spree_payments.updated_at")
or
Spree::Order.joins(:payments, :line_items).select("spree_orders.total, spree_orders.item_total, spree_payments.created_at, spree_payments.updated_at")
That is equivalent to this query
SELECT spree_orders.total,
spree_orders.item_total,
spree_payments.created_at,
spree_payments.updated_at
FROM "spree_orders"
LEFT OUTER JOIN "spree_payments" ON "spree_payments"."order_id" = "spree_orders"."id"
LEFT OUTER JOIN "spree_line_items" ON "spree_line_items"."order_id" = "spree_orders"."id"
You can use select_all method.This method will return an instance of ActiveRecord::Result class and calling to_hash on this object would return you an array of hashes where each hash indicates a record.
Order.connection.select_all("SELECT
orders.item_total,
orders.total,
payments.created_at,
payments.updated_at
FROM
public.payments,
public.orders,
public.line_items,
public.variants
WHERE
payments.order_id = orders.id AND
orders.id = line_items.order_id").to_hash
I'm trying to sort ordered by updated_at of User record, which is associated from Code table.
#codes = Code.joins(:user).where('body like ?', "%"+params[:search]+"%").order('user.updated_at DESC').page(params[:page]).per(10)
However, it won't let me sort:(
This is the error message I get.
Error Message
Mysql2::Error: Unknown column 'user.created_at' in 'order clause
Your database table should be users not user (plural not singular). Update your order method as follows:
order('users.updated_at DESC')
I am using Ruby on Rails 3.2.2 and I would like to know if in scope methods it is possible to "dynamically" join a table only if that table is not joined yet. That it, I have:
def self.scope_method_name(user)
joins(:joining_association_name).where("joining_table_name.user_id = ?", user.id)
end
I would like to make something like the following:
# Note: the following code is just a sample in order to understand what I mean.
def self.scope_method_name(user)
if table_is_joined?(joining_table_name)
where("joining_table_name.user_id = ?", user.id)
else
joins(:joining_association_name).where("joining_table_name.user_id = ?", user.id)
end
end
Is it possible / advised to make that? If so, how could / should I proceed?
I would like to use this approach in order to avoid multiple database table statements in INNER JOIN of SQL queries (in some cases it seems to make my SQL querying not working as expected since multiple table statements) and so to use the scope_method_name without caring related SQL query concerns (in my case, without caring to join database tables).
Note: It could raise SQL errors (for example, errors as-like "ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'joining_table_name.user_id' in 'where clause'") when you have not joined yet the database table (for example, this could happen when you run code like ClassName.scope_method_name(#user) without to previously join the joining_association_name and so without to join the related joining_table_name table).
Where is the method loaded? to check if an association has been loaded. You could try to use that.
if association_name.loaded?
where("joining_table_name.user_id = ?", user.id)
else
joins(:joining_association_name).where("joining_table_name.user_id = ?", user.id)
end
I'm using rails and am trying to figure out how to use ActiveRecord within the method to combine the following into one query:
def children_active(segment)
parent_id = Category.select('id').where('segment' => segment)
Category.where('parent_id'=>parent_id, 'active' => true)
end
Basically, I'm trying to get sub categories of a category that is designated by a unique column called segment. Right now, I'm getting the id of the category in the first query, and then using that value for the parent_id in the second query. I've been trying to figure out how to use AR to do a join so that it can be accomplished in just one query.
You can use self join with a alias table name:
Category.joins("LEFT OUTER JOIN categories AS segment_categories on segment_categories.id = categories.parent_id").where("segment_categories.segment = ?", segment).where("categories.active = ?", true)
This may looks not so cool, but it can implement the query in one line, and there will be much less performance loss than your solution when data collection is big, because "INCLUDE IN" is much more slower than "JOIN".