Oracle SQL WHERE MONTH = N - sql

In my select I am using this
(TRUNC(TO_DATE(TIMESTAMP, 'dd.mm.yyyyHH24:mi'))) TIMESTAMP,
to get the following output in a date format: e.g. 22/04/2016
Now I want to add a statement in my WHERE-clause to show only dates in special months, for example only dates which are in MARCH and APRIL
I tried using this:
WHERE (TRUNC(TO_DATE(TIMESTAMP, 'mm'))) in (3,4)
which gives me an error.
Thanks for helping.

Just use EXTRACT() on the timestamp:
WHERE EXTRACT(MONTH FROM timestamp) IN (3, 4)
This would match records from March and April.

In my select I am using this
(TRUNC(TO_DATE(TIMESTAMP, 'dd.mm.yyyyHH24:mi'))) TIMESTAMP,
to get the following output in a date format: e.g. 22/04/2016
TO_DATE takes a string value so your "TIMESTAMP" column will be implicitly converted to a string and then back to a date... which is unnecessary (and relies on the value of the NLS_TIMESTAMP_FORMAT session parameter to format the implicit conversion - which, if changed, will break the query); you can just do:
TRUNC( "TIMESTAMP" ) AS "TIMESTAMP"
If you want to then filter on different months then you can do (as suggested by Tim Biegeleisen):
WHERE EXTRACT( MONTH FROM "TIMESTAMP" ) IN ( 3, 4 )
or if you want a particular year then
WHERE TRUNC( "TIMESTAMP", 'MM' ) IN ( DATE '2016-03-01', DATE '2016-04-01' )
or, so you can use an index on the column:
WHERE "TIMESTAMP" >= DATE '2016-03-01'
AND "TIMESTAMP" < DATE '2016-05-01'

Related

How can I convert a string quarter year to a timestamp in Databricks SQL

In Databricks SQL, how can I convert a date in string format "2021Q2" to a timestamp with the last day of that quarter?
select
to_timestamp(
last_day(
to_date(
(left('2021Q4',4)||'-'||int(right('2021Q4',1)*3))||'-'||'1')))
from
my_table
It is a pity that Q is not working in formatting from string to date object (it is working only in reverse) - parsing Q with to_date(date, "YYYY'QQ") sadly will not work.
According to https://spark.apache.org/docs/latest/sql-ref-datetime-pattern.html:
Symbols of ‘E’, ‘F’, ‘q’ and ‘Q’ can only be used for datetime formatting, e.g. date_format. They are not allowed used for datetime parsing, e.g. to_timestamp.
Because of that we have to separate quarter and multiple by 4. Than convert it to date object (parse_ and take last_date of the month:
SELECT
last_day(
to_date(
concat(left("2021Q4", 4), int(right("2021Q4", 1))*3),
"yyyyMM")
) as last_day_of_quarter
Simple way :
select to_timestamp(last_day(concat('2021','-',0,4*3,'-01'))) as last_date_queter
Logic :
calculate the last month of quarter by using multiple with 3. example 4th quarter's last month calculated 12 (4*3)
concat (year,'-',-01) so that we can get the first day of respective month 2021-12-01
last_day we can use last date of the given date month.
finally , we can convert the date into timestamp to_timestamp

Oracle SQL: Syntax for WHERE clause with one date between two others

Apologies in advance, feel like I'm missing something fundamental here.
I'm limiting a query WHERE one field (already in date format) is between two others:
SELECT Stuff
FROM Table
WHERE datefield BETWEEN (currentdate - 28) AND (current_date - 1)
This returns nothing. Now if I format both as dates explicitly and look for a single date:
SELECT Stuff FROM Table
WHERE TO_DATE(datefield, 'YYYY-MM-DD') = TO_DATE((current_date - 1), 'YYYY-
MM-DD')
That returns the single day's results as intended. However, if I then try something along the lines of:
SELECT Stuff FROM Table
WHERE TO_DATE(datefield, 'YYYY-MM-DD') >= TO_DATE((current_date - 28),'YYYY-
MM-DD')
This returns the entire table, including dates from long before (current_date - 28)
And finally if I try the BETWEEN after explicitly formatting:
SELECT Stuff FROM Table
WHERE TO_DATE(datefield, 'YYYY-MM-DD') BETWEEN TO_DATE((current_date - 28)
,'YYYY-MM-DD') AND TO_DATE((current_date - 1) ,'YYYY-MM-DD')
This returns nothing again.
Any help would be much appreciated.
SELECT Stuff
FROM Table
WHERE datefield BETWEEN (currentdate - 28) AND (current_date - 1)
Will return values between the 28 days before the current date at the same time of day as now and 1 day before the current date at the same time of day as now. So, if you run this at 10:23 today then it will get results before 10:23 yesterday and if your results for yesterday were all entered in the afternoon then they will not be included in the results.
SELECT Stuff
FROM Table
WHERE TO_DATE(datefield, 'YYYY-MM-DD') = TO_DATE((current_date - 1), 'YYYY-MM-DD')
TO_DATE( date_string, format_model ) takes a string as the first argument so Oracle will implicitly convert your date to a string using the NLS_DATE_FORMAT session parameter. So your query is effectively:
SELECT Stuff
FROM Table
WHERE TO_DATE(
TO_CHAR(
datefield,
( SELECT VALUE FROM NLS_SESSION_PARAMETERS WHERE PARAMETER = 'NLS_DATE_FORMAT' )
),
'YYYY-MM-DD'
)
=
TO_DATE(
TO_CHAR(
(current_date - 1),
( SELECT VALUE FROM NLS_SESSION_PARAMETERS WHERE PARAMETER = 'NLS_DATE_FORMAT' )
),
'YYYY-MM-DD'
)
Firstly, don't ever rely on an implicit conversion. Secondly, depending on what your NLS_DATE_FORMAT session parameter is your query will either: raise an exception if the format model does not match YYYY-MM-DD; or give you gibberish dates (i.e. if your default format model is RR-MM-DD then you'll lose the centuries from your dates; if it is DD-MM-YY then you'll swap days and years - which might "work" [i.e. not raise an exception] for the next decade or so and then blow up horribly in February 2029); or it will work. However, this is a session parameter so users can change it and your query will randomly stop working without changing your SQL.
Assuming that your NLS_DATE_FORMAT is YYYY-MM-DD then this will effectively truncate your dates and you could do it much simpler using:
SELECT Stuff
FROM Table
WHERE TRUNC(datefield) = TRUNC(current_date - 1)
This will get all the results (regardless of time of day) for yesterday.
What you probably want is:
SELECT Stuff
FROM Table
WHERE datefield >= TRUNC( currentdate - 28 )
AND datefield < TRUNC( current_date )
As it will get all the results from Midnight 28 days ago to before midnight today.
If this doesn't work then you need to check your date values:
SELECT TO_CHAR( datevalue, 'YYYY-MM-DD HH24:MI:SS' )
FROM table;
You will possibly find that the dates are stored with the year in the 1st century AD (i.e. 0018-10-24 09:50:00 as the value) and this will (probably) be because dates were uploaded as a string with a 2-digit year (YY-MM-DD) when a 4-digit year (YYYY-MM-DD) was expected so Oracle will assume the century is 0.

oracle compare a date with the current date

I have to convert a column to a date and then compare the month of the column with the current month.
The column looks like this :
Date
0117
0217
0317
..
I know how to convert it but cant compare it.
select date,to_date(date, 'mmyy')
from table
where ????
any ideas?
You can convert the value to a date using to_date():
select to_date(mmyy, 'MMYY')
from t;
Note that I renamed the column mmyy to clarify what it contains.
This returns the first day of the month.
The result of to_date() can then be compared to the current date. For instance, to match the first of date of the month:
where to_date(mmyy, 'MMYY') = trunc(sysdate)
If you want to match everything in the month, just use an appropriate comparison:
where to_char(to_date(mmyy, 'MMYY'), 'YYYY-MM') = to_char(sysdate, 'YYYY-MM')
or, more simply:
where mmyy = to_char(sysdate, 'MMYY')
You can convert the current date to a string and use string comparisons (which would allow you to use an index on your column):
SELECT *
FROM your_table
WHERE your_date_column = TO_CHAR( SYSDATE, 'MMYY' )
or you can convert the column to a date and compare it (which would not use an index on your column but could use a function-based index, if you created one):
SELECT *
FROM your_table
WHERE TO_DATE( your_date_column, 'MMYY' ) = TRUNC( SYSDATE, 'MM' )

uisng to_date function still get date format picture ends before converting entire input string error

I have the following code where I want to see if a date is less than a year ago:
select id
from mytable
where id= :p_id
and (to_date(trunc(sysdate), 'yyyy-mm-dd') - to_date(datewhen, 'yyyy-mm-dd')) < 365;
I keep getting the error:
ORA-01830: date format picture ends before converting entire input
string
Looking at other question with the same error on StackOverflow I see the solution usually is to use the to_date function which I am doing so I am unsure why this is occuring. The datewhen field is of type Date.
Do not use to_date() with the columnes of DATE data type. to_date() converts character string to a value of DATE data type. It makes no sense to convert the DATE to DATE. In a first step datewhen column of type DATE will be implicitly converted into a character data type by using the default date format (that's most probably not 'yyyy-mm-dd') and this is the culprit of the ORA-01830 error.
So your statement should look something like this:
select id from mytable where id = :p_id and (trunc(sysdate) - trunc(datewhen)) < 365;
I'd calculate the difference in the months or years instead of days:
... where months_between(sysdate, datewhen) < 12
If your datewhen column is char/varchar formatted as yyyy-mm-dd then you have to do the to_date conversion on datewhen, but not on SYSDATE: it's already a date and doesn't need to be converted.
To filter on a date within the past 365 days, compare it to SYSDATE - 365:
select id
from mytable
where id = :p_id
and to_date(datewhen, 'yyyy-mm-dd') > sysdate - 365;
But a year isn't always 365 days: on leap years it's 366 days. To get a one year ago value that's always correct, subtract an interval of one year from the current date:
select id
from mytable
where id = :p_id
and datewhen > sysdate - interval '1' year;
One more thing: the Oracle DATE type isn't just a date; it's a date and a time. SYSDATE returns the current date and time. Try this query:
select to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss') from dual;
Unless you run this at exactly midnight you'll see a time component as well.
Say your query runs on 2 September 2017 at 10 AM and you're looking for a date within the past year. You'd expect to get the date 3 September 2016, but you wouldn't because at 10 AM SYSDATE is 3 September 2016 at 10:00:00. That's greater than the plain date 3 September 2016, which is 3 September 2016 at 0:00:00, so records with a datewhen of `2016-09-03' won't be included.
To ignore the time component of an Oracle DATE value, use TRUNC. Your final query should look something like this:
select id
from mytable
where id = :p_id
and datewhen > trunc(sysdate) - interval '1' year;
you use TO_DATE function when the value in character format
Syntax
The syntax for the TO_DATE function in Oracle/PLSQL is:
TO_DATE( string1 [, format_mask] [, nls_language] )

YYYYMMDD to YYYYMM in oracle

I have a column with DATE datatype in a table.
I am trying to retrieve the column values in YYYYMM format. My select query looks like below
select *
from tablename
where date column = to_char(to_date('12/31/4000','MM/DD/YYYY'),'YYYYMM');
I am getting below exception.
ORA-01847: day of month must be between 1 and last day of month
Appreciate any input on this.
I think the simplest method is:
where to_char(datecolumn, 'YYYYMM') = '400012'
Or, if you prefer:
where to_char(datecolumn, 'YYYYMM') = to_char(to_date('12/31/4000', 'MM/DD/YYYY'), 'YYYYMM');
Syntax-wise, the right hand date (to the right of the equals) is OK. But you are doing a character comparison, not a date comparison.
This works for me in multiple databases:
select to_char (to_date('12/31/4000','MM/DD/YYYY'),'YYYYMM')
from dual;
Even though your column is named DATE_COLUMN, you are comparing based on characters in the query.
So, try this instead - this compares based on dates (NOT a character comparison) and truncates off the hour, minute, ETC. so you are only comparing the DAY:
select * from DATE_TAB
where TRUNC(DATE1, 'DDD') = TRUNC(to_date('12/31/4000','MM/DD/YYYY'),'DDD');
NOTE: The DATE1 field above is a DATE field. If you're DATE_COLUMN is not a DATE field, you must
convert it to a DATE datatype first (using TO_DATE, ETC.)
Assuming that "date_column" is actually a date, and that you have an index on date_column, you can do something like this to return the data quickly (without truncating dates in all rows to do a comparison):
with dat as (
select level as id, sysdate - (level*10) as date_column
from dual
connect by level <= 100
)
select id, date_column
from dat
where date_column between to_date('11/1/2013', 'MM/DD/YYYY') and last_day(to_date('11/2013 23:59:59', 'MM/YYYY HH24:MI:SS'))
Here I just dummy up some data with dates going back a few years. This example picks all rows that have a date in the month of November 2013.
If your date_column's data-type is DATE, then use
select *
from tablename
where TO_CHAR(date_column,'YYYYMM') = to_char (to_date('12/31/4000','MM/DD/YYYY'),'YYYYMM');
If your date_column's data-type is VARCHAR, then use:
select *
from tablename
where date_column = to_char (to_date('12/31/4000','MM/DD/YYYY'),'YYYYMM');
I somehow feel your error is because you have a space between date and column as
"date column". If the field name in the table is "COLUMN", then just removing the word "DATE" from your original query would suffice, as:
select *
from tablename
where column = to_char(to_date('12/31/4000','MM/DD/YYYY'),'YYYYMM');
If your column (YYYYMMDD) is in number format, the simplest way to get YYYYMM would be
select floor(DATE/100)
from tablename;