So I've been trying to fetch some daily data with SYSDATE on a date type YYYYMMDD as following:
SELECT dates, trunc(calendar_date, 'DD') calendar_dates, weekday_nbr
FROM db.date
WHERE dates BETWEEN to_char(TRUNC(SYSDATE)-2, 'YYYYMMDD') AND to_char(TRUNC(SYSDATE)-1, 'YYYYMMDD')
But now I'm trying to use the same but on a YYYY+MM+Week date type with not much success
I tried using:
SELECT T time, period, fiscal_week
FROM db.time
WHERE time BETWEEN to_char(TRUNC(SYSDATE)-2, 'W') AND to_char(TRUNC(SYSDATE)-1,'W')
With time as a 7 digit number, and period and fiscal week as a 2 digit number
Knowing that there's no way I can truncate such date type, how can TRUNC SYSDATE YYYY+MM+Week to get the data on the last 2 weeks?
Also I was thinking about maybe getting the totals from a set day and then dropping all but the last 2 weeks, but on the long run maybe that would be time consuming.
Knowing that there's no way I can truncate such date type, how can TRUNC SYSDATE YYYY+MM+Week to get the data on the last 2 weeks?
Assuming that your fiscal weeks are from Monday-Sunday then you can truncate to the start of the ISO week (which is always Midnight on Monday) and use that for the basis of the comparison:
SELECT *
FROM db.time
WHERE dates >= TRUNC(SYSDATE, 'IW') - INTERVAL '14' DAY
AND dates < TRUNC(SYSDATE, 'IW')
If you have a column that is for weeks then you should still use a DATE data type and add a CHECK constraint (and can use virtual columns to generate the week and the year):
CREATE TABLE time (
dt DATE
CHECK (dt = TRUNC(dt, 'IW')),
year NUMBER(4,0)
GENERATED ALWAYS AS (EXTRACT(YEAR FROM dt)),
month NUMBER(2,0)
GENERATED ALWAYS AS (EXTRACT(MONTH FROM dt)),
week NUMBER(1,0)
GENERATED ALWAYS AS (FLOOR((dt - TRUNC(dt, 'MM'))/7) + 1),
time VARCHAR2(7)
GENERATED ALWAYS AS (
CAST(
TO_CHAR(dt, 'YYYYMM')
|| (FLOOR((dt - TRUNC(dt, 'MM'))/7) + 1)
AS VARCHAR2(7)
)
)
-- ...
);
fiddle
Then you can use the logic above on the date column.
If you do not have a DATE column then you will need to convert your YYYYMMW number into a DATE and then use the logic above.
For example, if the logic for your fiscal weeks (which you have not described) is that the first week of each month starts on the first Monday of the month then you can convert the YYYYMMW number to a DATE using:
SELECT NEXT_DAY(
TO_DATE(SUBSTR(time, 1, 6), 'YYYYMM') - INTERVAL '1' DAY,
'MONDAY'
) + INTERVAL '7' DAY * (SUBSTR(time, 7, 1) - 1) AS week_start
FROM db.time
and then could use it to filter the table using:
SELECT *
FROM (
SELECT t.*,
NEXT_DAY(
TO_DATE(SUBSTR(time, 1, 6), 'YYYYMM') - INTERVAL '1' DAY,
'MONDAY'
) + INTERVAL '7' DAY * (SUBSTR(time, 7, 1) - 1) AS week_start
FROM db.time t
)
WHERE week_start >= TRUNC(SYSDATE, 'IW') - INTERVAL '14' DAY
AND week_start < TRUNC(SYSDATE, 'IW')
If you have different logic for calculating when fiscal weeks start then you will need to apply that logic to the conversion.
Related
I am looking to filter my reports so they gather all the data to Friday.
I.e. today is the 12th and I would like my report to gather info from my date range 5th to the 11th. Then tomorrow on the 13th still get the data from the 5th to the 11th.
just a weekly report that comes out on a Friday.
I cant use date diff on the server it doesn't let me on this Oracle
I was using this where (date >= trunc(SYSDATE) - 7) but I cant seem to get it to do Friday.
I did a lot of reading and there is a post about levels....... and saw this script. It shows the Friday but I have no idea how to get it to filter on my date column.
WITH dates AS (SELECT TRUNC(SYSDATE, 'mm') + LEVEL -11 dt
FROM dual
CONNECT BY LEVEL <= 22)
SELECT dt,
to_char(dt, 'fmDay') day_of_dt,
TRUNC(dt + 3, 'iw') - 3 prev_fri_incl_today,
TRUNC(dt + 2, 'iw') - 3 prev_fri_not_incl_today
FROM dates;
If you want the values from Saturday of the previous week until Friday of the current week (which, if it is currently Monday-Friday will contain future dates) then:
SELECT *
FROM table_name
WHERE date_column >= TRUNC(SYSDATE, 'iw') - 2
AND date_column < TRUNC(SYSDATE, 'iw') + 5
If you want to include a full historic week (i.e. if it is current Monday-Friday then get last week's range):
SELECT *
FROM table_name
WHERE date_column >= TRUNC(SYSDATE - 5, 'iw') - 2
AND date_column < TRUNC(SYSDATE - 5, 'iw') + 5
fiddle
I am trying to convert char date format "YYYY-WW" in ORACLE to date for calculating by week in year but have a trouble with error message format code cannot appear in date input format
If i write
TO_DATE(TO_CHAR(TO_DATE('1970-01-01 07:00:00', 'YYYY-MM-DD HH:MI:SS'),'YYYY-MM'),'YYYY-MM')
It will be normal
But if i write
TO_DATE(TO_CHAR(TO_DATE('1970-01-01 07:00:00', 'YYYY-MM-DD HH:MI:SS'),'YYYY-WW'),'YYYY-WW')
The message error format code cannot appear in date input format appear. I don't have no idea how to convert it right
Thanks for any advice
You can use:
TO_DATE( year || '-01-01', 'YYYY-MM-DD' ) + INTERVAL '7' DAY * (week - 1)
For your code:
SELECT TO_DATE( TO_CHAR(dt, 'YYYY') || '-01-01', 'YYYY-MM-DD' )
+ INTERVAL '7' DAY * (TO_CHAR(dt, 'WW') - 1) AS week_start
FROM (
SELECT TO_DATE('1970-01-01 07:00:00', 'YYYY-MM-DD HH24:MI:SS') AS dt
FROM DUAL
);
If you want to use ISO weeks (which always start on a Monday, rather than counting from the 1st January as WW does) then:
TRUNC( TO_DATE( iso_year || '-01-04', 'YYYY-MM-DD' ), 'IW')
+ INTERVAL '7' DAY * (iso_week - 1)
db<>fiddle here
You can have a look at this for guidance. https://asktom.oracle.com/pls/apex/asktom.search?tag=week-of-year-in-sql-confusing
There isn't a built-in way to convert a week number back to a date, as the result would be a bit arbitrary - which of the (up to) seven days in the week should it return?
If you want the first day of the week, as would be found by truncating the original date to WW precision (which is based on the day of the week of the first day of the year - docs), then you can reverse that process by getting the first day of the year and then adding the number of days in the specified number of weeks.
To do that you need to split your string into the two component parts:
substr('1970-01', 1, 4)
substr('1970-01', 6, 2)
and convert the first part to a date:
to_date(substr('1970-01', 1, 4) || '-01-01', 'YYYY-MM-DD')
and the second part to a number of weeks:
to_number(substr('1970-01', 6, 2))
then subtract one from that number of weeks, multiply by seven, and add it to the base date:
select to_date(substr('1970-01', 1, 4) || '-01-01', 'YYYY-MM-DD')
+ (7 * (to_number(substr('1970-01', 6, 2)) - 1))
from dual
1970-01-01
It's bit hard to tell that has been adjusted, so trying with today's date, which is week 30 of 2022:
select to_date(substr('2022-30', 1, 4) || '-01-01', 'YYYY-MM-DD')
+ (7 * (to_number(substr('2022-30', 6, 2)) - 1))
from dual
2022-07-23
which matches what trunc(sysdate, 'WW') gives.
db<>fiddle
If you want a specific day of the week then you'll need to figure out how much to adjust that, based on what day of the week the first day of the year was.
Select
Extract (year from TO_DATE('1970-01-01 07:00:00', 'YYYY-MM-DD HH:MI:SS')) || '-' ||
TO_CHAR(TO_DATE('1970-01-01 07:00:00', 'YYYY-MM-DD HH:MI:SS'),'WW')
From dual
If you are starting from a string like '1970-01-01 07:00:00' and want the first day of the corresponding week, you don't need to convert to and from strings and dates repeatedly; you just need to convert that string to a date once, and truncate it:
trunc(to_date('1970-01-01 07:00:00'), 'WW')
or if you want the ISO week:
trunc(to_date('1970-01-01 07:00:00'), 'IW')
For your example that would give:
select to_date('1970-01-01 07:00:00') as dt,
trunc(to_date('1970-01-01 07:00:00'), 'WW') as ww,
trunc(to_date('1970-01-01 07:00:00'), 'IW') as iw
from dual;
DT
WW
IW
1970-01-01 07:00:00
1970-01-01 00:00:00
1969-12-29 00:00:00
And for today it would give:
select to_date('2022-07-28 07:00:00') as dt,
trunc(to_date('2022-07-28 07:00:00'), 'WW') as ww,
trunc(to_date('2022-07-28 07:00:00'), 'IW') as iw
from dual;
DT
WW
IW
2022-07-28 07:00:00
2022-07-23 00:00:00
2022-07-25 00:00:00
db<>fiddle
I'm using Oracle SQL Developer and I would like to make a SELECT that brings all the products sold from the last day of the previous month (but only products sold from 4 pm on the last day of the previous month) to the current day (only until 8 am of the current day).
For example, today is 7/21/2022. If I run this query today, it should bring data from:
06/30/2022 above 16:00hrs -> 07/21/2022 until 08:00hrs
You can use TRUNC(value, 'MM') to find midnight of the 1st day of the current month and then subtract 8 hours to find the start of the range and then use TRUNC(value) to find midnight of today and add 8 hours to find the end of the range:
SELECT *
FROM table_name
WHERE date_column >= TRUNC(SYSDATE, 'MM') - INTERVAL '8' HOUR
AND date_column <= TRUNC(SYSDATE) + INTERVAL '8' HOUR;
You can use TRUNC to get to the first day of a date's month. Then subtract one day and add sixteen hours. And it's again TRUNC that you use to get back to the beginning of a day (midnight) to which you can add eight hours.
select *
from mytable
where dt >= trunc(sysdate, 'mm') - interval '1' day + interval '16' hour
and dt < trunc(sysdate, 'dd') + interval '8' hour
order by dt;
how to get current month to date values in oracle 12c sql developer
Select dcc.EMPLOYEECODE, dcc.DUTYID, dtt.DUTYDESC
from DUTYCHART dcc
join DCDUTYCHART dtt
on dcc.RESTCODE = dtt.RESTCODE
and dcc.DUTYID = dtt.DUTYID
and trunc(date) = trunc(sysdate)
Here am getting current date but I want to show current month and previous month, I tried some functions like add-months but it didn't worked for me
You can use :
trunc(sysdate, 'MONTH') -- CURRENT MONTH START DATE
ADD_MONTHS(trunc(sysdate, 'MONTH'), -1) -- PREVIOS MONTH START DATE
If you want to get data of previous month then your query's where clause must include: Replace (trunc(date) = trunc(sysdate)) with one of the following according to your need
trunc(date) BETWEEN ADD_MONTHS(trunc(sysdate, 'MONTH'), -1)
AND trunc(sysdate, 'MONTH') - 1 -- PREVIOUS MONTH'S DATA
trunc(date) >= trunc(sysdate, 'MONTH') -- -- CURRENT MONTH'S DATA
trunc(date) >= ADD_MONTHS(trunc(sysdate, 'MONTH'), -1) -- PREVIOUS AND CURRENT MONTH'S DATA TOGETHER
Cheers!!
For the current month, use:
date >= trunc(sysdate, 'MONTH')
For the previous month, use:
(date >= trunc(sysdate, 'MONTH') - interval '1' month and
date < trunc(sysdate, 'MONTH')
)
There is no reason to truncate date for the comparison.
I need to fetch first 3 days record of the current month from Oracle database. Something like below,
Select * from test.purchase where create_ts=( first 3 days of the current month)
Select *
from test.purchase
where create_ts between trunc(sysdate,'mm') and trunc(sysdate,'mm') + 3
You can get the first day of the current month with the trunc(date) function, using the MM date format element.
select to_char(trunc(sysdate, 'MM'), 'YYYY-MM-DD Hh24:MI:SS') from dual;
TO_CHAR(TRUNC(SYSDA
-------------------
2017-06-01 00:00:00
You can then use date arithmetic to either add a number of days or an interval representing that number to get the fourth day of the month:
select to_char(trunc(sysdate, 'MM') + 3, 'YYYY-MM-DD Hh24:MI:SS') from dual;
TO_CHAR(TRUNC(SYSDA
-------------------
2017-06-04 00:00:00
If you want data up to the start of that fourth day, i.e. up to 23:59:59 on the 3rd, you can look for values less than midnight on the 4th:
select * from test.purchase
where create_ts >= trunc(sysdate, 'MM')
and create_ts < trunc(sysdate, 'MM') + 3;
You could potentially use between, but as that is inclusive you would need to specify the absolute latest time on the 3rd - checking whether the column is a date or a timestamp, which might change, and can be a little confusing. If you used between trunc(sysdate, 'MM') and trunc(sysdate, 'MM') + 3 then you would include any records at exactly midnight on the 4th, which isn't what you want. I find using >= and < clearer and less ambiguous, even if it is a little more typing.
If the column is actually a timestamp then you can cast the calculated dates to timestamp too, and/or an use interval for the upper bound:
select * from test.purchase
where create_ts >= cast(trunc(sysdate, 'MM') as timestamp)
and create_ts < cast(trunc(sysdate, 'MM') + 3 as timestamp);
... or:
...
and create_ts < cast(trunc(sysdate, 'MM') as timestamp) + interval '3' day;