I want to write something like:
#meeting_requests = Meeting.where('meeting_time >= ? AND requestee_id IS ?
AND status = ?', Date.today, nil, "Active")
.joins(:requestor)
.where('birthyear >= ? AND birthyear <= ?',
current_user.birthyear - 10,
current_user.birthyear + 10 )
This works:
#meeting_requests = Meeting.where('meeting_time >= ? AND requestee_id IS ?
AND status = ?', Date.today, nil, "Active")
And this works:
#meeting_requests = Meeting.joins(:requestor)
.where('birthyear >= ? AND birthyear <= ?',
current_user.birthyear - 10,
current_user.birthyear + 10 )
And something like this works:
Meeting.joins(:requestor).where('birthyear > ?', 1900).where(status: "Active")
but I need to do a greater than query on the meeting_time, so I need to write it as a string I think?
But together both sql queries produce an error of: ambiguous column name: status: SELECT
I feel like I'm so close... what am I missing here?
This is a message that appears when it is not clear which table the column comes from. This should work:
...rest_of_statement.where('meetings.status' => 'Active')
Related
I have a simple view:
CREATE VIEW [dbo].[ApplicationSummary]
AS
SELECT
CONVERT(VARCHAR(50), NEWID()) AS ID,
ISNULL(AVG(ApplicationTime), 0) AS 'AvgApplicationTime',
ISNULL(AVG(ResponseTime), 0) AS 'AvgResponseTime',
ISNULL(CAST(1.0 * COUNT(CASE WHEN [IsAccepted] = 1 THEN 1 END) / COUNT(*) AS float), 0) AS 'PctAccepted'
FROM
[Application]
WHERE
(IsValid = 1)
AND (CreatedOn < CAST(GETDATE() AS date)
AND CreatedOn >= CAST(GETDATE()-30 AS date))
The idea is that it outputs 3 variables. The first 2 are simple 'averages', whereas the last one, 'PctAccepted' outputs a ratio.
I'm testing a table containing 4 rows — 3 of them are set to IsAccepted = true, so the result is 0.75 (3/4), which converts to 75%.
I'm trying to remove the need for a view and replicate it using Linq over my Entity Framework class.
Here is the important stuff from the query:
var startDate = DateTime.Today;
var endDate = DateTime.Today.AddDays(-30);
var q = r.Find(x => x.IsValid &&
x.CreatedOn < startDate && x.CreatedOn >= endDate)
.GroupBy(x => x)
.Select(g => new
{
AvgApplicationTime = (int)g.Average(i => i.ApplicationTime),
AvgResponseTime = (int)g.Average(i => i.ResponseTime),
ApprovalRatio = g.Count(i => i.IsAccepted == true) / (double)g.Count()
}).First();
return new ApplicationStats(q.AvgApplicationTime, q.AvgResponseTime, q.ApprovalRatio);
So far, I have the two averages outputting correctly, but the ratio is returning 1 (or 100%).
Initially, I thought it may be a rounding issue but I've outputted the result of this line: g.Count(i => i.IsAccepted == true) and it incorrectly returns 1.
I may have grouping in the wrong place, but am currently struggling to make it work.
Any help appreciated.
Found the answer.
Changed .GroupBy(x => x) to .GroupBy(x => 1).
Also g.Count(i => i.IsAccepted == true) can be simplified to g.Count(i => i.IsAccepted)
Here is the original logic
(scrape_datas = ScrapeData.find(
:all, :conditions =>
"artist_status = 'NOT_FOUND'
AND blacklisted = 1
AND extracted = 0
and not EXISTS(
SELECT * FROM artist_name_suggestions where original = artist_name
)
I've been able to split up the first part better
scrape_datas = ScrapeData.where(
:artist_status => 'NOT_FOUND',
:blacklisted => 1,
:extracted => 0
)
Although having issues getting the "and not EXISTS" query into the mix
and not EXISTS(
SELECT * FROM artist_name_suggestions where original = artist_name
)
Thanks!
Firstly you can extract simple scopes:
scope :not_found, where(:artist_status => 'NOT_FOUND')
scope :blacklisted, where(:blacklisted => 1)
scope :extracted, where(:extracted => 0)
Then add a query method (assume artist_name is a column of scrape_datas):
def self.no_suggestions
scrape_datas = ScrapeData.arel_table
suggestions = ArtistNameSuggestion.arel_table
where(ArtistNameSuggestion.where(
suggestions[:original].eq(scrape_datas[:artist_name])
).exists.not)
end
Now you can do something like this:
ScrapeData.not_found.blacklisted.extracted.no_suggestions
Give the following (already simplified) query in SQLite:
def self.calculate(year, month, user_id, partner_id)
where(':user_id = entries.user_id OR :partner_id = entries.user_id', {
:user_id => user_id,
:partner_id => partner_id
}).
where('entries.date <= :last_day', {
:last_day => Date.new(year, month, 1).at_end_of_month
}).
select('sum(case when joint = "f" and user_id = :user_id then amount_calc else 0 end) as sum_single' , {
:user_id => user_id
}).
group("strftime('%Y-%m', date)")
end
The full query has more sums with different case when statements and some of them depend on whether it is user_id oder partner_id. Unfortunately, Rails complains as select does not take the second parameter with the substitutions like where does. Is there any way to achieve what I want without running two queries, one for user_id and one for partner_id?
One can be so blind....instead of:
select('sum(case when joint = "f" and user_id = :user_id then amount_calc else 0 end) as sum_single' , {
:user_id => user_id
}).
just build the string:
select('sum(case when joint = "f" and user_id = ' + user_id.to_s + ' then amount_calc else 0 end) as sum_single').
As nobody answered, this is for the archives :)
Edit: Sorry, beware of that: as noted below, this is vulnerable.
So locally I have
#fooentries = Entry.where(:status => 'foo').where("created_at >= #{Date.today}")
Which runs fine, but when I deploy to Heroku it seems to be breaking it.
I asked a friend and he told me to do the following but this fails locally:
#fooentries = Entry.where(:status => 'foo').where("created_at >= #{Time.zone.now.beginning_of_day.to_s(:db)}")
Anyone?
EDIT: Doesn't matter, fixed it. This is what the query needs to be-
#fooentries = Entry.where(:status => 'foo').where('entries.created_at >= ?', Time.zone.now.beginning_of_day)
Would you try to escape the query, maybe it depends on the format your query is built
try
#fooentries = Entry.where(:status => 'foo').where("created_at >= ?", Date.today)
As per the edit above, this is what I needed -
#fooentries = Entry.where(:status => 'foo').where('entries.created_at >= ?', Time.zone.now.beginning_of_day)
Now i am inputting some data from a form and i have a code to search the database inputting several parameters as input conditions. Now if one the parameters is null (i.e) the field is unchecked i need to replace that parameter with something say * so that the search query is unaffected. How would i do that?
#report = Problem.find(:all, :conditions => ["problems.cause_id = ? and problems.location_id = ? and problems.device_id = ? and problems.priority_id = ?", Report.find_by_id(params[:id]).cause_id, Report.find_by_id(params[:id]).location_id, Report.find_by_id(params[:id]).device_id, Report.find_by_id(params[:id]).priority_id])
It would be better to not have that condition at all than to use *. In this case it's simple as all of your comparison operators are "=". That means you can use the hash form of conditions. Your code is also quite inefficient as you load the same report object 3 or four times. Your question about one of the params being null doesn't make sense for this reason: you just use the same param again and again. Also you set a variable called #report to be a Problem object which is confusing.
#report = Report.find_by_id(params[:id])
conditions = {:cause_id => #report.cause_id, :location_id => #report.location_id, :device_id => #report.device_id, :priority_id => #report.priority_id}
conditions.delete_if{|k,v| v.blank?}
#problem = Problem.find(:all, :conditions => conditions)
rep = Report.find_by_id(params[:id])
cause = rep.cause_id ? rep.cause_id : '*'
location = rep.location_id ? rep.location_id : '*'
device = rep.device_id ? rep.device_id : '*'
priority = rep.priority_id ? rep.priority_id : '*'
#report = Problem.find(:all,
:conditions => ["problems.cause_id = ? and
problems.location_id = ? and
problems.device_id = ? and
problems.priority_id = ?",
cause, location,
device, priority
]
)