ruby on rails parameter compare date with datetime? - sql

I receive this parameter: param[:date] = '2017-03-04'
and the column in my database is created_at with this format: '2017-01-01 09:21:23'
When I execute this query
Mymodel.where(created_at: params[:date])
It returns an empty array, and it is logic due the time that is not passed
I need all the rows that corresponds to the param date.
How can I do this? The time is not important in this case, I only need the date.
I am using postgres as db.
I need to select e.g. All Sell of a specific day and the column to search is created_at.

This is a type-coercion problem. Because the created_at field contains a date and time, your date is being converted into 2017-03-04 00:00:00 for the query. Anything that doesn't exactly match that timestamp will be excluded.
There are two approaches to solving this problem.
Database agnostic
Turn your date into a Range object. ActiveSupport provides the Date#all_day helper for this use-case.
date = Date.parse(params[:date])
MyModel.where(created_at: date.all_day)
Since Date::parse throws an exception if parsing fails, the real-world implementation would have to account for that
my_models = begin
date = Date.parse(params[:date])
MyModel.where(created_at: date.all_day)
rescue ArgumentError
MyModel.all
end
Postgres
You can cast your created_at field to date so that only the date part will be matched.
MyModel.where("created_at::date = ?", params[:date])

Related

sql teradata filtering on date - database version Teradata 15.10.06.02 and provider version Teradata.Net 15.11.0.0

my table has a date column. its data type is date. I confirmed it by going to table name>>columns and it says MTH_END_DT [DATE, Not NULL]
I want to filter my data for a particular date. If I put a condition where MTH_END_DT = '6/1/2018' I get an error select failed [3535] A character string failed conversion to a numeric value.
I followed this page. I used where MTH_END_DT = date '6/1/2018' and i get an error syntax error invalid date literal
I tried where cast(timestamp_column as date) = date '2013-10-22'; something like this and it throws error too
How should i filter my data?
There's only one reliable way to write a date, using a date literal, date 'yyyy-mm-dd'
where MTH_END_DT = DATE '2018-06-01'
For a Timestamp it's
TIMESTAMP '2018-06-01 15:34:56'
and for Time
TIME '15:34:56'
In SQL Assistant it's recommended to switch to Standard SQL format YYYY-MM-DD in Tools-Options-Data Format-Display dates in this format
I did have the similar problem when I was filtering a particular date for my query with Teradata. First method I tried was putting 'DATE' term as the following:
WHERE saledate = DATE'04/08/01' but this did not solve the problem.
I then used an approach I stumbled upon when surfing, finally it worked.
WHERE extract(year from saledate)=2004 AND extract(MONTH from saledate)=8 AND extract(DAY from saledate)= 1 source
I think this really should not be this long, but it worked.
It seems to me it’s most likely you have input the date format incorrectly? Maybe it includes a time by default.
For example
where MTH_END_DT = ‘2013-10-22-00:00:00:00’

Passing a user prompt as a date (or even a string) in Oracle SQL

I am using Business Objects, which runs on top of an Oracle SQL database. I do not have access to PL or any kind of SQL command line, and I do not have write access to the database. I can only run queries as single commands, requiring a defined set of columns to be output.
I am able to take data from user prompts, which appear in the SQL as:
#variable('Prompt1')
For example I can say:
SELECT
A.SomeDate
FROM
A
WHERE
A.SomeDate BETWEEN #variable('Start') AND #variable('End Date')
This is easy enough. It runs; requests the user to input some dates; and then returns all matches which are between them (inclusive).
The problem is, however, the users will be using Business Objects' "Infoview" system to run the queries, and the prompt system presents a date picker - which by default includes the time portion of the date ("01/01/2016 12:00:00 AM").
If the user does not delete the time portion, it can cause records to be missed, if the SomeDate value falls outside the selected time. For example, if I want to take all records of TODAY, then I technically want everything between 00:00:00 (midnight) and 23:59:59.
What I would really like to be able to do is use TRUNC around the query variable, as follows:
WHERE
A.SomeDate BETWEEN TRUNC(#variable('Start')) AND TRUNC(#variable('End Date'))
... however this causes a compilation error: "inconsistent datatypes: expected DATE got NUMBER". I don't know why Oracle would treat a prompt as a number datatype before it has compiled.
Does anyone know how I can take the #variable value and convert it into something that I will be able to truncate to a date value?
I'm therefore trying to figure out a way round this. One thing I had in mind was if I could possibly take the prompt variable and convert it explicitly into a date, using TO_DATE
Edit: it has been pointed out to me that TRUNC will have no effect, as the "12:00:00 AM" is already midnight. Therefore I think I have misunderstood TRUNC. It appears that it truncates it to midnight: whereas I thought it simply removed the time portion of the date altogether, meaning that matches would be returned at any time between 00:00:00 and 23:59:59.
What I really want is: if SomeDate has a time portion of, for example, 11:03 then how do I ensure that this will be included when an End Date prompt only specifies the day?
If you want to match SomeDate values between 00:00:00 on Start and 23:59:59 on End you can either adjust the end date to have that time instead of the default midnight, or use a range instead of between:
WHERE
A.SomeDate >= #variable('Start')
AND
A.SomeDate < #variable('End Date') + 1
The + 1 uses Oracle date arithmetic to give you the day after the variable value, so if the user picked "01/01/2016 12:00:00 AM" for both the start and end dates they would evaluate as 2016-01-01 00:00:00 and 2016-01-02 00:00:00 respectively. You can use the interval syntax if you prefer.
By using less-than for the upper limit you get all records where SomeDate is greater than or equal to the start date 2016-01-01 00:00:00 and less than the adjusted end date 2016-01-02 00:00:00 - which is the same as saying up to 2016-01-01 23:59:59. (Or if you has a timestamp column which has sub-second precision, up to 23:59:59.999...).
If the parser assumes the variable will be a string but it is actually a date - causing an 'inconsistent datatypes' error - then you could cast it to a date to satisfy the parser:
WHERE
A.SomeDate >= CAST(#variable('Start') AS DATE)
AND
A.SomeDate < CAST(#variable('End Date') AS DATE) + 1
or if it is actually passed as a string in the format you showed you can explicitly convert it:
WHERE
A.SomeDate >= TO_DATE(#variable('Start'), 'DD/MM/YYYY HH:MI:SS AM')
AND
A.SomeDate < TO_DATE(#variable('End Date'), 'DD/MM/YYYY HH:MI:SS AM') + 1
... making sure you have the correct format; from your example it could be DD/MM/YYYY or MM/DD/YYYY.
Try using TO_CHAR() and TO_DATE() together :
WHERE
A.SomeDate > TO_DATE(TO_CHAR(#variable('Prompt1'),'ddmmyyyy'),'ddmmyyyy')
First off, your problem is not coming from a time value in the prompt value, but rather the time value in SomeDate. Getting rid of that (making the date equal to midnight) will resolve the issue.
Your best bet, if you have the option of modifying the universe, is to create another object. I'm assuming you have an object named SomeDate whose SQL is a.somedate. Create another object, let's call it SomeDateOnly with a definition of trunc(a.somedate)* **.
Since SomeDateOnly will always be a midnight value, you can use Equal To with your prompts, which will produce SQL like:
trunc(a.somedate) = #variable('Prompt1')
which, when rendered by WebI, will produce:
trunc(a.somedate) = '16-08-2016 00:00:00'
This will return all records with a.somedate between 8/16/2016 at 00:00:00 and 8/16/2016 23:59:59.
Of course, you can use BETWEEN to select a range of dates:
trunc(a.somedate) between #variable('Start Date') and #variable('End Date')
Even if you don't have access to the universe, you can still use the above syntax by modifying WebI's generated SQL. (I'm assuming that's what you've been doing, anyway).
If the above works for you, then the following is irrelevant, but I wanted to address it anyway:
The reason for the "invalid number" error you were receiving is because of the way WebI formats dates for SQL. If you have this string in your query:
A.SomeDate = TRUNC(#variable('Prompt1'))
then WebI will replace the #variable(...) with a date string, and render it as the following before sending it to Oracle:
A.SomeDate = TRUNC('16-08-2016 00:00:00')
This, of course, makes no sense to the TRUNC() function as there's nothing to tell it that it's actually a date value.
You could to_date the prompt first, but you have to use the correct date format. WebI sets the nls_date_format for each session to a non-default format, so you would have to use:
A.SomeDate = TRUNC(to_date(#variable('Prompt1')),'dd-mm-yyyy hh24:mi:ss')
But again, this is irrelevant since you need to trunc somedate, not the prompt response values.
*Better still, rename SomeDate to SomeDateTime, and name the new object SomeDate
**This is pretty common - having multiple objects for the same source field. Sometimes you want the date/time value (for listing specific transactions), but sometimes you just need the date (for counting transactions by date). So having both available is very useful.

Sql Query using 'Like' is giving results but using '=' does not returns any result in Oracle

The Query using LIKE :(This query when fired gives the desired result)
select * from catissue_audit_event where event_timestamp like '16-DEC-14'
But when using query with '=' results in an empty resultset
select * from catissue_audit_event where event_timestamp='16-DEC-14'
Here event_timestamp is of type Date
Strange thing is that the query runs for other dates such as:
select * from catissue_audit_event where event_timestamp='15-DEC-14'
What can be the issue? I already checked for leading and trailing spaces in the data
Output after running the first query:
In Oracle a DATE (and of course a TIMESTAMP) column contains a time part as well.
Just because your SQL client is hiding the time, doesn't mean it isn't there.
If you want all rows from a specific day (ignoring the time) you need to use trunc()
select *
from catissue_audit_event
where trunc(event_timestamp) = DATE '2014-12-16';
Be aware that this query will not use an index on the event_timestamp column.
You should also not rely on implicit data type conversion as you do with the expression event_timestamp = '16-DEC-14. That statement is going to fail if I run it from my computer because of different NLS settings. Always use a proper DATE literal (as I have done in my statement). If you don't like the unambiguous ISO date, then use to_date():
where trunc(event_timestamp) = to_date('16-12-2014', 'dd-mm-yyyy');
You should avoid using month names unless you know that all environments (which includes computers and SQL clients) where your SQL statement is executed are using the same NLS settings. If you are sure, you can use e.g. to_date('16-DEC-14', 'dd-mon-yy')
The reason why this is different is different to the solution to your issue.
The solution to your issue is to stop performing date comparisons by implicit conversion to a string. Convert your string to a date to perform a date comparison:
select * from catissue_audit_event where event_timestamp = date '2014-12-16'
I cannot stress this enough; when performing a date comparison only compare dates.
Your column EVENT_TIMESTAMP is being implicitly (this is bad) converted to a date in accordance with your NLS_DATE_FORMAT, which you can find as follows:
select * from nls_session_parameters
This governs how date-data is displayed and implicitly converted. The reason why LIKE works and and = doesn't is because your NLS_DATE_FORMAT is masking additional data. In other words, your date has a time component.
If you run the following and then re-select the data from your table you'll see the additional time component
alter session set nls_date_format = 'yyyy-mm-dd hh24:mi:ss'
Thus, if you want all the data for a specific date without constraint on time you'll need to remove the time component:
select * from catissue_audit_event where trunc(event_timestamp) = date '2014-12-16'
have you tried matching the event_timestamp format example: DD-MMM-YY with the date that you are passing?

Fetching the records which are having all time stamp columns

I am trying to fetch the records which are having all time stamp columns.
I am using the following query to fetch the products that are created between the final date and (final date - 30) days, i.e products created during the last 30 days that fall in the 'final date' range.
I have products that are created on 30-OCT-2014. For the same products, the initiated date is 12-NOV-2014. However they are not being fetched when I using the below query.
SELECT A.ROW_ID,
A.PROD_NAME
FROM PROD A,
PROD_REL B
WHERE A.ROW_ID = B.PAR_ROW_ID
AND TO_DATE(A.CREATED_DT,'YYYY-MM-DD') BETWEEN (TO_DATE(B.FINAL_DATE,'YYYY-MM-DD') - 30)
AND (TO_DATE(B.FINAL_DATE,'YYYY-MM-DD'));
So, could you please let me know if I am missing something?
Here is a link to a SQLFiddle that demonstrates the problem.
… or just fix your format string TO_DATE(A.CREATED,'DD-MON-YYYY')
SQL Fiddle
Storing dates as DATE, is , of course, always a good starting point.
Since your data types are all dates, there is no need to use to_date. It's harmful, in fact, since to_date doesn't take a date as a parameter. Oracle has to do an implicit conversion from a date to a string, using your session's NLS_DATE_FORMAT which gets passed in to to_date and converted back to a date using the explicit format mask you specified. If the two conversions aren't using the same format mask, bad things happen.
Your WHERE clause just needs to be
AND a.created_dt BETWEEN b.final_date - 30
AND b.final_date
If I make that change, your SQLFiddle returns two rows

Query "Select max(date) from table where date <= somedate" not working

I am querying a SQLite database table as follows:
SELECT MAX(Date) from Intra360 WHERE Date <= "05/04/2013 00:00"
The right record in return should be the number 47, i.e. 04/04/2013 23:00:
However, the execution of this statement returns a different value:
I confess I know almost nothing about SQL, but this outcome is strange. Where am I being wrong?
NOTE "Intra360" is the name of the table and the field containing the dates is called "Date"
ADDITIONAL NOTE what I need is the closest available date to a user input. It is a Python program which is making some analysis but when the user inputs the dates is not necessarily true they will exist in the database. So I'm just trying to re-select them in a way that the proper SQL statement that will load the data to be used in the analysis won't fail execution because of the missing record. So "05/04/2013 00:00" is the user input, and the query should be done hence starting from 04/04/2013 (and not definetely 04/06/2013).
The comparisons are performed on strings with alphabetical ordering, not on datetime stamps with chronological ordering.
Store your datetimes in a format that compares the way you want. For example, unix epoch timestamps and ISO 8601 yyyy-MM-dd'T'HH:mm:ss datetimes have this property.
If you cannot influence how the data is stored, you can use substr() to mangle the timestamps in SQL. See e.g. Sqlite convert string to date for more.