Search table fields along with parent table using Foreign Key - ruby

I have 4 search fields in my index page of Employee table - id, due_date, employee_full_name, company_name.
Here, in search_parameters, I am checking if search parameters are present
search_parameters =
{:id => params[:id], :due_date => params[:due_date],
:employee_full_name => params[:employee_full_name]}
.select { |key,value| value.present?}
I am searching the columns of Employee table and it is working fine
#employees_search = Employee
.where(search_parameters, params[:id].to_i, params[:due_date],
params[:employee_full_name])
Here I am searching 'company_name' from Company table with company_id as the foreign key. This is also working fine.
#company_search = Employee
.where(company_id: Company
.where(company_name: params[:company_name]))
But I need to combine the above 2 queries so that user can search all 4 fields together. Somewhat like the below code.
#employees_search = Employee
.where(search_parameters, params[:id].to_i, params[:due_date],
params[:employee_full_name],
company_id: Company
.where(company_name: params[:company_name]))
the above query just gives search result of employee table and not the combined result. What is wrong with the queries?

Try this query using the active record querying using the or query by giving all the fields,
#employees_search = Employee
.where("id = ? or due_date = ? or employee_full_name = ?
or company_id in (?)", params[:id],params[:due_date],params[:employee_full_name],
Company.where('company_name = ?',params[:company_name]).pluck(:id))
Search all the fields in the Employee table using the '= ?' syntax and when coming to the company_id there may be multiple companies with the same name so use in (?) syntax, even if it works for single company.
This will give you all the employees with the values from the params and also including the employees who belong to that company.
This may solve your issue.

using #sravan answer, I arrived to following query, which worked perfectly.
search_parameters =
{:id => params[:id], :due_date => params[:due_date],
:employee_full_name => params[:employee_full_name],
:company_id => Company
.where('company_name = ?', params[:company_name])
.pluck(:id)}
.select { |key,value| value.present? }
#employees_search = Employee
.where(search_parameters, params[:id].to_i, params[:due_date],
params[:employee_full_name],:company_id => Company
.where('company_name = ?',params[:company])
.pluck(:id)
)

Related

ASP.NET Core / EF Core LINQ statement

I have 3 related entities:
PurchaseOrder (Id, ProjectId, Source, CompanyId, ...)
Company (Id, Name, ...)
Contacts (Id, CompanyId, Email, AutoEM, ...)
Each purchase order has a related company and each company can have one or more contacts where one of them is set as the primary or default contact (eg: AutoEM == true).
I would like the LINQ to return a set of PurchaseOrder rows for a selected ProjectId and include, on each row, the company name its for, and the contact email for the primary contact for that company.
I was able to get the PO and Company info displayed on my page, but have not been able to figure out how to include the primary contact which has AutoEM == true. Thank you in advance for any help.
pos = context.PurchaseOrder
.Where(p => p.ProjectId == Int32.Parse(id))
.Include(p => p.company)
.ToList();
So, you want to include the primary contact which has AutoEM == true.
The condition (where statement) should be applied to the include of Contacts. The use of "ThenInclude" is to guarantee that related Company is added first and then including related Contacts where AutoEM == true.
I suggest the following update to the code:
pos = context.PurchaseOrder
.Where(p => p.ProjectId == Int32.Parse(id))
.Include(p => p.company)
.ThenInclude(p => p.Contacts.Where(c => c.AutoEM == true))
.ToList();

Select from multiple tables based upon search term but good in performance

I have a query in which I pass the search term to filter the list of Companies, either by Email or company Title which is stored in another table (TranslationTexts) as Text column for multiple locales.
The query runs fine but it is very heavy and takes time. How can I make it more efficient?
See Table Diagram Image
The query:
gm.ListData = context.Companies.ToList()
.Where(a => a.AspNetUser.Email.NullableContains(searchTerm) ||
a.TitleTranslation.TranslationTexts
.Where(b => b.Text.NullableContains(searchTerm)).Any()
).Select(c => new ListCompany
{
CompanyID = c.CompanyID,
EmailID = c.AspNetUser.Email,
Title = c.TitleTranslation.TranslationTexts.FirstOrDefault(d => d.Locale == Locale).Text
}).ToList();

NotSupportedException for LINQ Queries

I am trying to get a list of a database table called oracleTimeCards whose employee id equals to the employeeID in employees list. Here is what I wrote:
LandornetSQLEntities db = new LandornetSQLEntities();
List<OracleEmployee> employees = db.OracleEmployees.Where(e => e.Office.Contains(officeName) && e.IsActive == true).Distinct().ToList();
var oracleTimeCards = db.OracleTimecards.Where(c => employees.Any(e => c.PersonID == e.PersonID)).ToList();
Anyone has any idea?
I'm going to assume you're using Entity Framework here. You can't embed calls to arbitrary LINQ extension methods inside your predicate, since EF might not know how to translate these to SQL.
Assuming you want to find all the timecards for the employees you found in your first query, you have two options. The simplest is to have a navigation property on your Employee class, named let's say TimeCards, that points to a collection of time card records for the given employee. Here's how that would work:
var oracleTimeCards = employees
.SelectMany(e => e.TimeCards)
.ToList();
If you don't want to do this for whatever reason, you can create an array of employee IDs by evaluating your first query, and use this to filter the second:
var empIDs = employees
.Select(e => e.PersonID)
.ToArray();
var oracleTimeCards = db.OracleTimecards
.Where(tc => empIDs.Contains(tc.PersonID))
.ToList();

LINQ querying a many-to-many relationship

I have an ASP.NET application that talks to an SQL database containing 4 tables:
Cities
States
StatesCities (maps Cities<=>States)
Customers (which stores the ID of the City they live in)
I need to get a count of how many customers live in a particular state. I can achieve this with the following SQL query:
select count(*) from Customers where CityID in
(
select sc.CityID from StatesCities sc, States s
where sc.StateID = s.StateID AND s.Name = 'Texas'
)
How can I express the equivalent of this query in LINQ, either using the EF or LINQ to SQL?
With the EF approach I've made it as far as:
var cities = db.Cities.Where(c => c.States.Any(s => s.Name == "Texas"));
but I'm not sure how to do the Customer/CityID match and count.
You could do something like this:
int CustomersCount=db.Customers.Count(c=>c.City.State.Name=="Texas");
or
var cities = db.Cities.Where(c => c.States.Any(s => s.Name == "Texas"));
int customersCount=Customers.Count(d=>cities.Any(x=>d.CityID==x.CityID);
#216 got me on the right track with the first suggestion, but because a City can exist in more than one State I needed to tweak the statement slightly:
int customersCount = db.Customers.Count(c => c.City.States.Any(s => s.Name == "Texas"));

How to find records that have duplicate data using Active Record

What is the best way to find records with duplicate values in a column using ruby and the new Activerecord?
Translating #TuteC into ActiveRecord:
sql = 'SELECT id,
COUNT(id) as quantity
FROM types
GROUP BY name
HAVING quantity > 1'
#=>
Type.select("id, count(id) as quantity")
.group(:name)
.having("quantity > 1")
Here's how I solved it with the AREL helpers, and no custom SQL:
Person.select("COUNT(last_name) as total, last_name")
.group(:last_name)
.having("COUNT(last_name) > 1")
.order(:last_name)
.map{|p| {p.last_name => p.total} }
Really, it's just a nicer way to write the SQL. This finds all records that have duplicate last_name values, and tells you how many and what the last names are in a nice hash.
I was beating my head against this problem with a 2016 stack (Rails 4.2, Ruby 2.2), and got what I wanted with this:
> Model.select([:thing]).group(:thing).having("count(thing) > 1").all.size
=> {"name1"=>5, "name2"=>4, "name3"=>3, "name4"=>2, "name5"=>2}
With custom SQL, this finds types with same values for name:
sql = 'SELECT id, COUNT(id) as quantity FROM types
GROUP BY name HAVING quantity > 1'
repeated = ActiveRecord::Base.connection.execute(sql)
In Rails 2.x, select is a private method of AR class. Just use find():
klass.find(:all,
:select => "id, count(the_col) as num",
:conditions => ["extra conditions here"],
:group => 'the_col',
:having => "num > 1")
Here is a solution that extends the other answers to show how to find and iterate through the records grouped by the duplicate field:
duplicate_values = Model.group(:field).having(Model.arel_table[:field].count.gt(1)).count.keys
Model.where(field: duplicate_values).group_by(&:field).each do |value, records|
puts "The records with ids #{records.map(&:id).to_sentence} have field set to #{value}"
end
It seems a shame this has to be done with two queries but this answer confirms this approach.

Resources