I have the following statement for a MySQL DB.
if(cms_hagent.ti_availtime > '0',1,0) as "Total Available Time"
I need to convert it to query an Informix DB. Any suggestions on the proper syntax?
Use CASE which is part of SQL-92 standard
CASE WHEN cms_hagent.ti_availtime > '0' THEN 1 ELSE 0 END AS "Total Available Time"
Related
I have a CSV that has a string column called name, It has things like "3 months pasta".
I want to map this to an existing DB table. The DB record has it saved as "3 months Pasta".
If I try Food.where(name: row['name']) it will come up empty. because it is doing a direct string to string comparison between "3 months pasta" and "3 months Pasta".
I have tried this as well
Food.where('name LIKE ?', '%' + "3 months pasta" + '%')
Which did not work unless I uppercase the "p", what can I do to get the strings to match on both ends? I want to do a row['name'].parameterize.underscore to get it to a single case and single style and then doing the same from the DB and matching them. The issue is doing this could be costly converting all the names then doing the comparison.
Is there something that I could do to achieve this?
Try
Food.where("lower(name) = ?", row['name'].downcase)
Though the #Ursus’ answer is perfectly correct, I would go with native case insensitive search against DB:
Food.where('name = ? COLLATE utf8_general_ci', "3 months pasta")
ci in collation name stands for “case insensitive.”
After gathering data from a web service, I'm trying to pull out only those records that have a value for a particular field > 0. The field that I'm checking is a FixNum field. I have tried multiple things like .nil? or > 0 etc. But none of them seem to work.
Here is how the code goes:
results.each do |r|
# puts "came"
if r['efforRemaining'] % 1 != 0 #i tried r['efforRemaining'].nil? ..
# i have values like 0.4, 0.5 etc for the field, hence i need to check if the value is greater than 0 or not only
puts "came!"
puts "#{r['mstone']} ... #{r['assignee']['id']} ... #{r['effortRemaining'].to_f}"
end
end
Could somebody let me know how to do this?
thanks,
If puts r['effortRemaining'].inspect comes out in quote marks, that means it is a string and you need to convert it to a number before you compare it.
This should work:
if r['effortRemaining'].to_f > 0
I'm trying to find a database agnostic way of comparing dates with active record queries. I've the following query:
UserRole.where("(effective_end_date - effective_start_date) > ?", 900.seconds)
This works fine on MySQL but produces an error on PG as the sql it generates doesn't contain the 'interval' syntax. From the console:
←[1m←[36mUserRole Load (2.0ms)←[0m ←[1mSELECT "user_roles".* FROM "user_roles" WHERE "user_roles"."effective_end_date" IS NULL AND ((effective_end_d
ate - effective_start_date) > '--- 900
...
')←[0m
ActiveRecord::StatementInvalid: PG::Error: ERROR: invalid input syntax for type interval: "--- 900
When I run this with the to_sql I option I get:
irb(main):001:0> UserRole.where("effective_end_date - effective_start_date) > ?", 900.seconds).to_sql
=> "SELECT \"user_roles\".* FROM \"user_roles\" WHERE \"user_roles\".\"effective_end_date\" IS NULL AND (effective_end_date - effective_start_date) >
'--- 900\n...\n')"
All help appreciated.
If your effective_end_date and effective_start_date columns really are dates then your query is pointless because dates have a minimum resolution of one day and 900s is quite a bit smaller than 86400s (AKA 25*60*60 or 1 day). So I'll assume that your "date" columns are actually datetime (AKA timestamp) columns; if this is true then you might want to rename the columns to avoid confusion during maintenance, effectively_starts_at and effectively_ends_at would probably be good matches for the usual Rails conventions. If this assumption is invalid then you should change your column types or stop using 900s.
Back to the real problem. ActiveRecord converts Ruby values to SQL values using the ActiveRecord::ConnectionAdapters::Quoting#quote method:
def quote(value, column = nil)
# records are quoted as their primary key
return value.quoted_id if value.respond_to?(:quoted_id)
case value
#...
else
"'#{quote_string(YAML.dump(value))}'"
end
end
So if you try to use something as a value for a placeholder and there isn't any specific handling built in for that type, then you get YAML (a bizarre choice of defaults IMO). Also, 900.seconds is an ActiveSupport::Duration object (despite what 900.seconds.class says) and the case value has no branch for ActiveSupport::Duration so 900.seconds will get YAMLified.
The PostgreSQL adapter provides its own quote in ActiveRecord::ConnectionAdapters::PostgreSQLAdapter#quote but that doesn't know about ActiveSupport::Duration either. The MySQL adapter's quote is also ignorant of ActiveSupport::Duration. You could monkey patch some sense into these quote methods. Something like this in an initializer:
class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
# Grab an alias for the standard quote method
alias :std_quote :quote
# Bludgeon some sense into things
def quote(value, column = nil)
return "interval '#{value.to_i} seconds'" if(value.is_a?(ActiveSupport::Duration))
std_quote(value, column)
end
end
With that patch in place, you get intervals that PostgreSQL understands when you use an ActiveSupport::Duration:
> Model.where('a - b > ?', 900.seconds).to_sql
=> "SELECT \"models\".* FROM \"models\" WHERE (a - b > interval '900 seconds')"
> Model.where('a - b > ?', 11.days).to_sql
=> "SELECT \"models\".* FROM \"models\" WHERE (a - b > interval '950400 seconds')"
If you add a similar patch to the MySQL adapter's quote (which is left as an exercise for the reader), then things like:
UserRole.where("(effective_end_date - effective_start_date) > ?", 900.seconds)
will do The Right Thing in both PostgreSQL and MySQL and your code won't have to worry about it.
That said, developing and deploying on different databases is a really bad idea that will make Santa Claus cry and go looking for some coal (possibly laced with arsenic, possibly radioactive) for your stocking. So don't do that.
If on the other hand you're trying to build database-agnostic software, then you're in for some happy fun times! Database portability is largely a myth and database-agnostic software always means writing your own portability layer on top of the ORM and database interfaces that your platform provides. You will have to exhaustively test everything on each database you plan to support, everyone pays lip service to the SQL Standard but no one seems to fully support it and everyone has their own extensions and quirks to worry about. You will end up writing your own portability layer that will consist of a mixture of utility methods and monkey patches.
can anyone please tell me how to write query in select_value.
I have tried,
ActiveRecord::Base.connection.select_value("select count(*) from leave_details where status= 'Pending' and 'employeedetails_id'=25")
but it showing error
invalid input syntax for integer: "employeedetails_id".
I am using PostgreSQL.
Single quotes are used to quote strings in PostgreSQL (and every other SQL database that even pretends to respect the SQL standard) so you're saying something like this:
some_string = some_integer
when you do this:
'employeedetails_id'=25
and that doesn't make any sense: you can't compare strings and integers without an explicit type cast. You don't need to quote that identifier at all:
ActiveRecord::Base.connection.select_value(%q{
select count(*)
from leave_details
where status = 'Pending'
and employeedetails_id = 25
})
If you even do need to quote an identifier (perhaps it is case sensitive or contains spaces), then you'd use double quotes with PostgreSQL.
Apparently you created your column as "EmployeeDetails_id" so that it is case sensitive. That means that you always have to use that case and you always have to double quote it:
ActiveRecord::Base.connection.select_value(%q{
select count(*)
from leave_details
where status = 'Pending'
and "EmployeeDetails_id" = 25
})
I'd recommend reworking your table to not use mixed case identifiers:
They go against standard Ruby/Rails naming.
They force you to double quote the mixed case column names everywhere you use them.
They go against standard PostgreSQL practice.
This is going to trip you up over and over again.
Executing SQL directly isn't really The Rails Way, and you lose any database portability by doing it that way.
You should create a model for leave_details. E.g.
rails g model LeaveDetails status:string employeedetails_id:integer
Then, the code would be:
LeaveDetails.where({ :status => 'Pending', :employeedetails_id => 25 }).count
I have a slightly complex time arithmetic problem.
I have a reminder system where the user can set "how many x before event" duration. For example: If I set '5 minutes' - I need to get reminder before 5 minutes of the event schedule.
In my reminder system, I have a cron which runs every minute and sends reminder mails. So far so good. I want to find all calendar events which are eligible for reminder (calendar entry whose scheduled time is between "5.minutes.from_now and 6.minutes.from_now"
I am trying the write the following where clause :
conds = "'when' >= '#{eval("#{cal.remind_before.to_s}.#{cal.remind_before_what.downcase}.from_now").to_s(:db)}' AND 'when' < '#{eval("#{cal.remind_before.to_s}.#{cal.remind_before_what.downcase}.from_now + 1.minutes").to_s(:db)}'"
#mail_calendar_for_reminder= Calendar.find(:all, :conditions=> conds)
Here cal.reminder_before = '5', cal.remind_before_what.downcase='minutes'
so the eval would be evaluating (5.minutes.from_now) and (6.minutes.from_now)
The resulting SQL statement is :
SELECT "calendars".* FROM "calendars" WHERE ('when' >= '2011-01-11 14:44:54' AND 'when' < '2011-01-11 14:45:54')
This SQL is syntactically and logically correct because it gets a time range of 5.minutes.from_now and 6.minutes.from_now. But it is not selecting eligible records. I suspect two things:
1. The SQL above is doing string comparisons rather than time comparisons.
2. The database entry for calendar's scheduled time has the following format :
2011-01-11 14:45:09.000000 --the 0's the end might be messing teh date comparisons.
I tried almost all sorts of date range arithmetic but could not get the eligible records in this query.
Depending on your server and its load, a one-minute window for cron might be a little optimistic.
What happens if you login to the dbms server and execute that SQL statement? Any rows returned? Any error messages?
You can try an explicit type cast. So
'when' >= CAST('2011-01-11 14:44:54' AS DATETIME) ...
Your dbms might require a different syntax for type casting and conversion. Search your docs.
Are your column names case sensitive? Is the column 'when' or 'When'? (Or wHen?)
This query returns your test event. Note the double quotes around the column name.
SELECT "calendars".*
FROM "calendars"
WHERE ("when" >= '2011-01-10 15:56'
AND "when" < '2011-01-10 15:57')