Prior to posting this question, I have looked at case when, but it doesn't solve my problem.
The scenario is, based on whether it is a Monday in the week, I need to fetch some data from a table. I can write it in PL/SQL block, but I want to achieve this in plain SQL.
Any suggestions please?
Assuming the tables have the same structure this would work:
select * from table1
where to_char(sysdate, 'DY') = 'MON'
union all
select * from table2
where to_char(sysdate, 'DY') != 'MON'
Using day literals like this is dependent on your NLS settings. So adjust the solution if you need to.
to_char(sysdate-3, 'DAY') will return MONDAY you can trim it and using decode return different value than null:
select decode(TRIM(to_char(sysdate-3, 'DAY')),'MONDAY', 1, null) from dual
EDIT:
In where you can
where decode(to_char(sysdate-3, 'fmDAY'), 'MONDAY', 1, null) =1
*sysdate-3 was choose because it's Thursday today
Related
I am trying to separate the time and date in one column to be independent off each other. I am new at writing scripts
this is my query:
select
*
from
[tablename]
where
to_date([column_name]) in ( '15-Jun-2021', '16-Jun-2021' )
and
to_char([column_name],'dd-Mon-yyyy HH:MM:ss') < '15-Jun-2021 19:54:30'
The way you put it, it would be
select *
from your_table
where date_column >= date '2021-06-15'
and date_column < to_date('15.06.2021 19:54:30', 'dd.mm.yyyy hh24:mi:ss')
because
date_column should be of date datatype. If it isn't, you'll have problems of many kinds in the future. Therefore,
don't to_date it, it is already a date
don't to_char it either, because you'd be comparing strings and get unexpected result. Use that function when you want to nicely display the result
the second condition you wrote makes the first one questionable. If date_column is less than value you wrote, then you can omit date '2021-06-16' from the first condition because you won't get any rows for that date anyway
date literal (date '2021-06-15') sets time to midnight, so condition I wrote should return rows you want
SQL> select date '2021-06-15' first,
2 to_date('15.06.2021 19:54:30', 'dd.mm.yyyy hh24:mi:ss') second
3 from dual;
FIRST SECOND
------------------- -------------------
15.06.2021 00:00:00 15.06.2021 19:54:30
SQL>
I run two queries and they are returning different results. Please help me find what am I missing.
select UPPER(TO_CHAR(Hire_date,'MONTH'))
from employees
returns a list of months(containing "2" entries for 'MARCH')
SELECT COUNT(EMPLOYEEID) "March Joinees"
FROM Employees
WHERE UPPER(TO_CHAR(Hire_date,'MONTH')) = 'MARCH';
returns 0 as count
to_char(<date>, 'Month') produces a string of length equal to the greatest length of any month name (in the current session's language) - it does so by padding with spaces. This is why the second query produces no results; if you wrap the upper.... within trim(...) it will work, but it would be better not to use to_char(..., 'Month') for this kind of query to begin with. I am sure you came to the same conclusion but you just want to know what is going on...
Here's an illustration. It may seem like the first column in the result is the string 'March'; however, the second column doesn't lie: the result in the first column is actually 'March ' (with four spaces at the end).
select to_char(date '2016-03-01', 'Month') as month_as_string,
length( to_char(date '2016-03-01', 'Month') ) as len
from dual
;
MONTH_AS_STRING LEN
--------------- ---
March 9
Then you may ask why Oracle made such a weird choice. That's a much tougher question. Anyway, this behavior is documented. http://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements004.htm#i34924 and scroll down to MONTH in table 2.15.
As stated by mathguy already, 'MONTH' makes padding with spaces. Try
SELECT '"'||TO_CHAR(Hire_date, 'Month')||'"' FROM employees
to see the effect. Use either function TRIM or Format Model Modifiers FM
Then result of TO_CHAR(Hire_date, 'Month') depends your current session NLS_DATE_LANGUAGE value. Other session may get "März" or "Μάρτιος". Specify either date language or use Month numbers.
Actually UPPER(TO_CHAR(Hire_date,'MONTH')) is redundant. Format MONTH returns month name in upper case, you don't have to make UPPER() again.
Taking all this into account you should use one of the expressions below
WHERE TO_CHAR(Hire_date, 'fmMONTH', 'NLS_DATE_LANGUAGE = english') = 'MARCH'
WHERE UPPER(TO_CHAR(Hire_date, 'fmMonth', 'NLS_DATE_LANGUAGE = english')) = 'MARCH'
WHERE TRIM(TO_CHAR(Hire_date, 'MONTH', 'NLS_DATE_LANGUAGE = english')) = 'MARCH'
WHERE TO_CHAR(Hire_date, 'MM') = '03'
WHERE EXTRACT(MONTH FROM Hire_date) = 3
I am using Oracle XE on my machine.
Defined a table as :
Name Type
ENAME VARCHAR2(20)
DOJ DATE
Firing a simple select:
select * from test1.tasty1;
ENAME DOJ
sat 08-DEC-16
So ok - I am aware that DATE field has time component in it.
The following query using TRUNC works fine:
select * from test1.tasty1 where trunc(DOJ) = '08-DEC-16';
Now I wanted to test the 'to_date' function - but none of the below queries worked - wonder why ?
select * from test1.tasty1 where DOJ =
to_date('08-12-2016','DD-MM-YYYY');
select * from test1.tasty1 where
DOJ = to_date('08-DEC-2016','DD-MON-YYYY');
select * from
test1.tasty1 where DOJ = to_date('08-DEC-16','DD-MON-YY');
select
* from test1.tasty1 where DOJ = to_date('08-DEC-16','dd-mon-RR');
Had taken a look at the following on SO:
Oracle TO_DATE not working
so not sure what is wrong here ?
From your question and comments, it appears that this is the sequence of events which happened.
You did the following INSERT into your table:
INSERT INTO test1.tasty1 VALUES ('sat', SYSDATE)
Keep in mind that dates in Oracle have both a date and a time component. So even though you did insert the date '2016-12-08' you also inserted a time component. As a result, the following query is not returning any records:
SELECT * FROM test1.tasty1 WHERE DOJ = '2016-08-12'
This is probably because you never specified the time component, and therefore the record you inserted earlier is not matching. If you want to compare only the date portion, you can use TRUNC as follows:
SELECT * FROM test1.tasty1 WHERE TRUNC(DOJ) = '2016-08-12'
The solution to your problem moving forward would be to wrap SYSDATE with TRUNC during the insert, if you really only want to deal with the date components.
By the way, the format '08-DEC-16' used as a literal will not be recognized by Oracle as a valid date. Instead, use '2016-12-08'.
Have you tried like this as comparison of date with date is correct:
select * from test1.tasty1 where to_date(DOJ,'DD-MM-YYYY') = to_date('08-12-2016','DD-MM-YYYY');
Compare apples with apples and not with mangoes.
What it worked from is instead of make a date to compare, change the date column to char with to_char(datecol, 'DD-MM-YYYY') = '01-01-2022'
I wanna catch the date in my table which is written like this "20140205101309" I tried to get by many ways, but i was not able to catch it so how to modifiy my query to catch it ?
select * from my.DETAIL a where A.DATE
between to_DATE('YYYYMMDD hh24:mi:ss','28-dec-2013 12:00:00')
and to_date ('YYYYMMDD hh24:mi:ss','2-feb-2014 00:00:00');
thank you in advance
Make a.call_date a date before comparing:
select *
from operation.reject_detail a
where to_date(a.call_date, 'YYYYMMDDHHMISS') between
to_date('28-12-2013 12:00:00','DD-MM-YYYY HH24:MI:SS') and
to_date('02-02-2014 00:00:00','DD-MM-YYYY HH24:MI:SS' );
Assuming 20140205101309 is: 2014, februari, 5 10:13:09
If you are not interested in the time part do this:
select *
from operation.reject_detail a
where to_date(substr(a.call_date,1,8), 'YYYYMMDD') between
to_date('28-12-2013','DD-MM-YYYY') and
to_date('02-02-2014','DD-MM-YYYY');
Storing dates as strings is bad practice, but since that is what you have and it's in a relatively sensible format, you can just compare it as a string:
select * from my.DETAIL a
where A.DATE between '20131228120000' and '20140202000000'
Or to ignore the time part on the table and include the full second date:
select * from my.DETAIL a
where A.DATE between '20131228000000' and '20140202235959'
There doesn't seem to be much point converting everything to DATE types, particularly if your column is indexed. If it isn't indexed than you could just look at the date part:
where substr(A.DATE, 1, 8) between '20131228' and '20140202'
Say I issue:
select date_field from table1;
date_field is like '25.11.2009'
I will try to change the positions of date fields with the month and vice versa. (of course for days > 12 some manipulations)
TO_DATE( MOD(SUBSTR(TO_CHAR(a.A_DATE, 'DD.MM.YYYY'), 4, 2), 12) || '.' ||
SUBSTR(TO_CHAR(a.A_DATE, 'DD.MM.YYYY'), 1, 2) ||
SUBSTR(TO_CHAR(a.A_DATE, 'DD.MM.YYYY'), 6, 4),
'DD.MM.YYYY')
THE THING IS THAT THE VALUE RETURNED FROM MOD() function is a number, i.e. for 01.07.2009 --> I get 1 for date, not '01' as expected. Later on I cannot get the date.
Is there a shortcut solution to my problem?
I suspect you need to seriously reconsider what you are trying to do.
I think what you started with is that you want to simply change the formatting of the date, e.g. change '25.11.2009' to '11.25.2009'.
If date_field is actually a DATE type, there is no inherent formatting stored in the field. It is a numeric value representing a specific date and time. It is formatted into text when you SELECT it in SQLPlus or some other tool, but that formatting is not stored in the table.
If you want to view the date in a particular format, you use the TO_CHAR function to force it. You can also set a default format model for a single session, a single client, or the whole database using NLS_DATE_FORMAT.
I used:
CASE MOD(SUBSTR(TO_CHAR(a.birthday, 'DD.MM.YYYY'), 1, 2), 12)
WHEN 1 THEN '01'
WHEN 2 THEN '02'
WHEN 3 THEN '03'
WHEN 4 THEN '04'
WHEN 5 THEN '05'
WHEN 6 THEN '06'
WHEN 7 THEN '07'
WHEN 8 THEN '08'
WHEN 9 THEN '09'
WHEN 10 THEN '10'
WHEN 11 THEN '11'
WHEN 12 THEN '12'
END
not very elegant but works :)
yli> "I am somehow anonymising the date, actually Hire Date of employees, to be used in a test environment."
So here was your actual requirement. If you want to change some dates, you don't need to use the date/string conversion functions (TO_CHAR/TO_DATE) at all. Oracle supports arithmetic operations on date values directly.
If you want to randomize your dates why not just use something like:
select date_field + dbms_random.value * 100 from table1;
Does this work?
TO_DATE(TO_CHAR(a.A_DATE, 'DD/MM/YYYY'), 'MM/DD/YYYY')
Have you tried TO_CHAR(<date>, '<format>')?