First Monday of last month - oracle

I have to get the date of the first Monday of the previous month for an Oracle query.
The ms SQL is
select dateadd (day, (9 - datepart(dw, eomonth(getdate(), -2)))%7, eomonth(getdate(), -2))
but there is no dateadd function in Oracle.

Here you go:
SQL> alter session set nls_date_language = 'english';
Session altered.
SQL> alter session set nls_date_Format = 'dd.mm.yyyy day';
Session altered.
SQL>
SQL> select next_day(add_months(trunc(sysdate, 'mm'), -1), 'monday') first_monday
2 from dual;
FIRST_MONDAY
--------------------
02.03.2020 monday
SQL>
What does it do?
truncate today's date (SYSDATE) to 1st of month ('mm')
subtract 1 month (add_months)
use next_day function, along with the 'monday' parameter

You can use:
TRUNC(TRUNC(add_months(dt, -1), 'mm') + 6, 'iw')
This subtracts a month from the specified date, truncates it to the 1st of the month, then adds 6 days to it before finally truncating it to the start of the iso week (which is always a Monday).
You need to add 6 to the first of the month to allow the appropriate Monday to count as the first Monday of the month (otherwise you could end up picking the last Monday of the previous month.
You can see it working [here[(https://dbfiddle.uk/?rdbms=oracle_18&fiddle=c25bc32b3223b954e8fcb02b9b76ffd5)

Related

Charts in Oracle Apex

Hi everyone I wanna ask u about how I can bring data last 24 hours into bar charts, is there any methods to make it please
I have this table without data
datetime
clientchannel
servicename
service_count
13_02_2022 9:35
*****
notification
2
It is a WHERE clause you need, I presume. Something like this:
select ...
from your_table
where datetime >= sysdate - 1;
Why? Because - when you subtract a number from DATE datatype value in Oracle - it subtracts that many days.
SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';
Session altered.
SQL> select sysdate right_now,
2 sysdate - 1 yesterday
3 from dual;
RIGHT_NOW YESTERDAY
------------------- -------------------
13.02.2022 11:01:34 12.02.2022 11:01:34
SQL>
If you store date values as strings (which means that DATETIME column is declared as e.g. VARCHAR2(20), and that's really bad idea), then you first have to convert it to a valid date datatype value - use TO_DATE function with appropriate format mask:
where to_date(datetime, 'dd_mm_yyyy hh24:mi') >= sysdate - 1
[EDIT] If you want to go 60 minutes back, then subtract that many minutes:
SQL> select sysdate right_now,
2 sysdate - interval '60' minute an_hour_ago
3 from dual;
RIGHT_NOW AN_HOUR_AGO
------------------- -------------------
14.02.2022 07:09:30 14.02.2022 06:09:30
SQL>

Error: ORA-01848: day of year must be between 1 and 365 (366 for leap year) while extracting month and year from DateColumn(varchar(10))

SELECT TO_CHAR(TO_DATE(Column_d, 'dd/mm/yyyy'), 'YYYY-MM') as Date_y FROM Table_d
Even want to get quarter from the same date which is again giving me the error ORA-01848 like
SELECT (CASE WHEN (TO_CHAR(TO_DATE(Column_d, 'dd/mm/yyyy'), 'mm')) IN ('01','02','03') THEN 'Q1'
WHEN (TO_CHAR(TO_DATE(Column_d, 'dd/mm/yyyy'), 'mm')) IN ('04','05','06') THEN 'Q2'
WHEN (TO_CHAR(TO_DATE(Column_d, 'dd/mm/yyyy'), 'mm')) IN ('07','08','09') THEN 'Q3'
ELSE 'Q4' END as QTR
FROM Table_d
The way I see it, nothing of what you posted returns ORA-01848. It is - usually, if not always - related to the DDD date format mask which represents day number within the year.
For example, this is correct, as day number 001 equals the 1st of January:
SQL> select to_date('001-2020', 'ddd-yyyy') from dual;
TO_DATE('0
----------
01.01.2020
This returns ORA-01848 as there's no day 405 in this (nor any) year:
SQL> select to_date('405-2020', 'ddd-yyyy') from dual;
select to_date('405-2020', 'ddd-yyyy') from dual
*
ERROR at line 1:
ORA-01848: day of year must be between 1 and 365 (366 for leap year)
So: if you're doing anything like this, make sure that stored values are correct; I presume that not all of them are.
Besides, that's what happens when people store dates as strings into VARCHAR2 (instead of DATE datatype) columns. I'm not saying that you're the cause, but you certainly are a victim here.
[EDIT]
Julian date, eh? In a comment, you said that you used such a query:
Select TO_CHAR(TO_DATE(Julian_dateColumn+1900000, 'YYDDD'), 'YYDDD'), 'DD/MM/YYYY') as column_d from sometable
I doubt it as it is invalid (I suppose you have superfluous , 'YYDDD')).
Anyway, I have no idea why you tried to "convert" Julian date in such a manner. There's a simple and correct way to do so. Here's how:
This is today's date (21.05.2020) presented as Julian date:
SQL> select to_char(sysdate, 'j') julian from dual;
JULIAN
-------
2458991
That's kind of values you have stored in the table. In order to convert it to format you wanted (yyddd), you'd
SQL> select to_char(to_date(2458991, 'j'), 'yyddd') as column_d from dual;
COLUM
-----
20142
I suggest you use this instead of code you currently have, i.e.
SQL> create or replace view table_d as
2 select to_char(to_date(julian_datecolumn, 'j'), 'yyddd') as column_d
3 from sometable;
View created.
SQL> select * From table_d;
COLUM
-----
20142
SQL>

How can we achieve last month record in oracle

I am new to oracle and I am writing a query where I have to fetch last month
My query:
select to_char(sysdate,'MON') from dual
But it is giving me
AUG which is current month.
I want the output as JUL which is last month
How can we achieve last month record.
select to_char(ADD_MONTHS (SYSDATE, -1),'MON') from dual
--Move ahead one month:
ADD_MONTHS (SYSDATE, 1);
--Move backward 1 month:
ADD_MONTHS (SYSDATE, -1);
http://www.oracle.com/technetwork/issue-archive/2012/12-jan/o12plsql-1408561.html
Oracle Database offers several built-in functions for shifting a date
by the requested amount or finding a date:
ADD_MONTHS—adds the specified number of months to or subtracts it from a date (or a timestamp)
NEXT_DAY—returns the date of the first weekday named in the call to the function
LAST_DAY—returns the date of the last day of the month of the specified date

Set day (1-31) portion only for date column in oracle

I need to set only the day portion of a date in oracle but retain month and year. Can you tell me what to do?
E.g. If date is 01-JAN-15 then i want to set day to 15 as 15-JAN-15.
1* select sysdate, trunc(sysdate, 'MONTH')+14 from dual
SQL> /
SYSDATE TRUNC(SYSDA
----------- -----------
25-sep-2015 15-sep-2015
SQL>

How to get the first day of the week, depending on NLS

I want to get the date of the first day of the week but I want it to be dependant to NLS parameters. Say , when I run it on America it should give me Sundays date, but in Turkey it should give me Monday..
select trunc(to_date(sysdate,'dd-mm-yy'),'iw')from dual;
How can I make it dependant?
According to the documentation, trunc(sysdate, 'IW') gives you:
Same day of the week as the first day of the calendar week as defined by the ISO 8601 standard, which is Monday
As you've seen, that is clearly not NLS-dependent.
You might think using W would give you the non-ISO, NLS-dependent, version, but it does something different - the same day of the week as the first day of the month. So run now, that will give you Monday, regardless of your settings, since July 1st was a Monday.
So you need either D, DY or DAY - they all behave the same:
alter session set nls_territory = 'AMERICA';
select trunc(sysdate, 'D') from dual;
TRUNC(SYS
---------
14-JUL-13
alter session set nls_territory = 'TURKEY';
select trunc(sysdate, 'D') from dual;
TRUNC(SYSD
----------
15/07/2013
Incidentally, your original query is doing to_date(sysdate,'dd-mm-yy'). sysdate is already a date. You're forcing an implcit conversion from that date to a string, which will use your NLS_DATE_FORMAT, and then an explicit conversion back to a date using dd-mm-yy. Not only is that pointless, it would break if your NLS_DATE_FORMAT didn't match (roughly, there is quite a bit of leeway) the dd-mm-yy you use explicitly:
alter session set nls_date_format = 'dd/mm/yyyy';
select to_date(sysdate,'dd-mm-yy') from dual;
TO_DATE(SY
----------
18/07/2013
alter session set nls_date_format = 'dd-mon-rr';
select to_date(sysdate,'dd-mm-yy') from dual;
TO_DATE(S
---------
18-jul-13
alter session set nls_date_format = 'mm/dd/yyyy';
select to_date(sysdate,'dd-mm-yy') from dual;
select to_date(sysdate,'dd-mm-yy') from dual
*
ERROR at line 1:
ORA-01843: not a valid month
alter session set nls_date_format = 'yyyy-mm-dd';
select to_date(sysdate,'dd-mm-yy') from dual;
select to_date(sysdate,'dd-mm-yy') from dual
*
ERROR at line 1:
ORA-01861: literal does not match format string
... etc. And your NLS_DATE_FORMAT is inherited from NLS_TERRITORY by default, so this is likely to be an issue if you're expecting to deal with multiple regions anyway.
When u use iso week, it is same for all territories. It returns always mondays.
Instead of use this;
select sysdate your_date,
trunc(sysdate,'IW') iso_start_of_week,
to_char(sysdate,'D') your_territory_day,
trunc(sysdate)- to_char(sysdate,'D') + 1 this_is_what_u_want
from dual

Resources