Is there a functon similar to DateDiff in MonetDB which can calculate number of weeks between two dates - monetdb

Consider two dates, "01-Jan-2011' & '01-Oct-2011'.
I wish to calculate number of weeks in between these dates.
I have tried the following:
select extract ( week from ( (current_date+ interval '5' day) - current_date ));
It returns error " no such unary operator 'week(day_interval)'"
I am able to find number of days by using following :
select extract ( day from ( (current_date+ interval '5' day) - current_date ));
the line above returns the output
Is there any way I can achieve the same?
Further, MonetDB considers week from Monday to Sunday(1-7). Is there any way this can be updated/ customised to Sunday to Saturday.
Thanks.

There are a couple of possibilities that I can think of:
select date '2011-10-01' - date '2011-01-01';
results in a INTERVAL DAY value, actually expressed in seconds of the difference, i.e. 23587200.000. This you could divide by (72460*60), i.e. the number of seconds in a week. But it's still an INTERVAL type, not an INTEGER.
Another way is to first convert the date to integers: the number of seconds since "the epoch" (Jan 1, 1970):
select epoch_ms(date '2011-10-01');
This actually give milliseconds since the epoch, so an extra factor of 1000.
This result you can then manipulate to get what you want:
select (epoch_ms(date '2021-02-02') - epoch_ms(date '2020-12-31')) / (7*24*60*60*1000);
This results in a HUGEINT value (if you have 128 bit integers in your system, i.e. anything compiled with GCC or CLANG), so you can convert this to INTEGER:
select cast((epoch_ms(date '2011-10-01') - epoch_ms(date '2011-01-01')) / (7*24*60*60*1000) as integer);

Related

select unique trunc(sysdate-370 + level, 'IW') AS datetime from dual connect by level <= 360 order by datetime

Can someone explain me what does the below oracle query do and what is it's output?
select unique trunc(sysdate-370 + level, 'IW') AS datetime from dual
connect by level <= 360 order by datetime;
select sysdate-370 + level AS datetime
from dual
connect by level <= 360;
Will generate 360 rows starting with the current date/time minus 370 days plus one day per row. So rows between 369 and 10 days before the current date/time.
TRUNC( datetime, 'IW' ) will truncate the date to the start of the ISO week (midnight on Monday of that week - irrespective of the NLS settings for date language and/or territory that affect some other options for truncating dates). So you will end up with duplicate rows for each generated row that is in the same week.
The UNIQUE keyword will get rid of those duplicate rows.
The order by datetime will order the results in ascending date order - however, the rows are generated in ascending order so this clause is unnecessary.
So the output will be 52 or 53 rows (depending on what the current day of the week is) starting with Monday midnight of each week containing the date 369 days before the current day up until the week containing 10 days before the current date.
The output (when run on 13th September 2017) is 52 rows (I skipped a few):
05-SEP-2016
12-SEP-2016
19-SEP-2016
26-SEP-2016
03-OCT-2016
...
31-JUL-2017
07-AUG-2017
14-AUG-2017
21-AUG-2017
28-AUG-2017
According to documentation trunc(dateval, 'IW') truncates to:
Same day of the week as the first day of the calendar week as defined by the ISO 8601 standard, which is Monday
connect by level <= N is a trick for producing a set of N rows with level values from 1 to N.

Difference in two dates not coming as expected in Oracle 11g

I get some data through a OSB Proxy Service and have to transform that using Xquery. Earlier the transformation was done on the database but now it is to be done on the proxy itself. So I have been given the SQL queries which were used and have to generate Xquery expressions corresponding to those.
Here is the SQL query which is supposed to find the difference between 2 dates.
SELECT ROUND((CAST(DATEATTRIBUTE2 AS DATE) -
CAST(DATEATTRIBUTE1 AS DATE) ) * 86400 ) AS result
FROM SONY_TEST_TABLE;
DATEATTRIBUTE1 and DATEATTRIBUTE2 are both of TIMESTAMP type.
As per my understanding this query first casts the TIMESTAMP to DATE so that the time part is stripped then subtracts the dates. That difference in days in multiplied with 86400 to get the duration in seconds.
However, when I take DATEATTRIBUTE2 as 23-02-17 01:17:19.399000000 AM and DATEATTRIBUTE1 as 23-02-17 01:17:18.755000000 AM the result should ideally be 0 as the dates are same and i'm ignoring the time difference but surprisingly the result comes as 1. After checking I found that the ( CAST(DATEATTRIBUTE2 AS DATE) - CAST(DATEATTRIBUTE1 AS DATE) ) part aparently does not give an integer value but a fractional one. How does this work?? o_O
Any help is appreciated. Cheers!
EDIT : So got the problem thanks to all the answers! Even after casting to DATE it still has time so the time difference is also calculated. Now how do I implement this in XQuery? See this other question.
Oracle DATE datatype is actually a datetime. So casting something as a date doesn't remove the time element. To do that we need to truncate the value:
( trunc(DATEATTRIBUTE2) - trunc(DATEATTRIBUTE1) )
you should try this to find difference by day
SELECT (trunc(DATEATTRIBUTE2) -
trunc(DATEATTRIBUTE1) ) AS result
FROM SONY_TEST_TABLE;
alternative 2
you can use extract like below:
SELECT ROUND (
EXTRACT (MINUTE FROM INTERVAL_DIFFERENCE) / (24 * 60)
+ EXTRACT (HOUR FROM INTERVAL_DIFFERENCE) / 24
+ EXTRACT (DAY FROM INTERVAL_DIFFERENCE))
FROM (SELECT ( TO_TIMESTAMP ('23-02-17 01:17:19', 'dd-mm-yy hh24:mi:ss')
- TO_TIMESTAMP ('23-02-17 01:17:17', 'dd-mm-yy hh24:mi:ss'))
INTERVAL_DIFFERENCE
FROM DUAL)

To count the number of weeks between two dates in oracle

I have used the below query to find the number of weeks between two dates:
select count(week_id)
from fw
where week_begin_date >= '2015-01-01'
and week_end_date <= '2015-12-31';
Expected result should be 53 but the actual result is 51.
Kindly help on this.
Can't you just use the week of year function? subtract if needed...
select to_char(to_date('12/31/2015','MM/DD/YYYY'),'WW') from dual;
select To_Number(to_char(to_date('12/31/2015','MM/DD/YYYY'),'WW')) -
To_number(to_char(to_date('01/01/2015','MM/DD/YYYY'),'WW')) +1
from dual;
We have to add +1 because weeks start at 1 not 0.
Now maybe you're after the ISO week format which would be IW instead of WW.
WW: Week of year (1-53) where week 1 starts on the first day of the year and continues to the seventh day of the year.
IW: Week of year (1-52 or 1-53) based on the ISO standard.
I know this is a very old thread, but I used a modified version of this code today that I thought might be beneficial for someone else. My modification solves for the fractional week issue and the removal of the minus sign:
SELECT
CEIL(
ABS(
(
TO_DATE('20160101','YYYYMMDD')
- TO_DATE('20161231','YYYYMMDD')
) / 7
)
) AS DT
FROM DUAL
The ABS function takes the absolute value of the result of subtracting the two dates, thereby eliminating the minus sign if it exists (I switched the order of the dates to demonstrate this). The CEIL function rounds up any fractional week to the next whole week (I changed the year to 2016 to demonstrate this - CEIL is logically equivalent to the ROUNDUP function in Excel). NOTE: We have to apply the ABS function first (inner parenthesis) because CEIL will also round up negative numbers, which would in effect round the weeks down if ABS were applied after CEIL. The result of this calculation is 53 (subtraction of the dates returns about -52.142857, ABS removes the minus sign, CEIL rounds up to 53).
I hope this ends up being useful to someone. Thanks.
Did you try this:
SELECT
REPLACE((
to_date('20151231','yyyymmdd') - to_date('20150101','yyyymmdd')
)/7, '-', '')
FROM
DUAL

convert minutes to hh/mi/ss format in oracle query

I want to know the query which converts minutes to the format of hh/mi/ss in Oracle.I 've already seen lot of same questions from many forums but nothing helped me to get the exact result.
The query I used -Select to_char(to_date(mod(100,60),'mi'),'hh/mi/ss') from dual;
But I don't know how to get the hour value.Because mod function returns only the remainder I don't know how to take the quotient part and substitute into the hour field.
I suppose there are two ways of storing "minutes" in an Oracle database - you can either store them in a field whose datatype is INTERVAL DAY TO SECOND, or you can store them in a NUMBER. The simplest case to handle is the INTERVAL - in this case, the TO_CHAR function converts the value to a string of the form SDD HH:MM:SS.FFFFFF, where 'S' is sign ('+' or '-' as intervals can be positive or negative), DD = days, HH= hours, 'MM' = minutes, 'SS' = seconds, and 'FFFFFF' = fractions; thus, to get the HH:MI:SS all we need to do is use the SUBSTR function, as in
SUBSTR(TO_CHAR(I_VAL), 5, 8)
where I_VAL is an INTERVAL DAY TO SECOND value.
If the value to be converted is in a numeric field it gets a bit messy as we have to compute the individual field values, then subtract the previous fields as part of getting the next field. However, since the value stored is in minutes instead of seconds it's not particularly difficult:
create table TST (N_VAL NUMBER,
I_VAL INTERVAL DAY TO SECOND);
INSERT INTO TST(N_VAL, I_VAL) VALUES (666, INTERVAL '666' MINUTE);
SELECT N_VAL,
TRUNC(N_VAL/60) AS HOURS,
N_VAL-(TRUNC(N_VAL/60) * 60) AS MINUTES,
0 AS SECONDS,
TO_CHAR(I_VAL),
SUBSTR(TO_CHAR(I_VAL), 5, 8) AS HMS_FROM_INTERVAL
FROM TST;
SQLFiddle here
Best of luck.

Selecting the minimum difference between two dates in Oracle when the dates are represented as UNIX timestamps

There are many question posted about getting the difference between two dates in Oracle. My question is requires the query to do a couple more things.
Here's how far I have got at the moment
select m_bug_t.date_submitted, m_bug_history_t.date_modified
from m_bug_t, m_bug_history_t
where m_bug_t.id = m_bug_history_t.bug_id
and field_name = 'status'
and new_value = '100'
So far I get a set of date pairs returned like this
date_submitted | date_modified
1314894774 | 1315906468
...
...
I want to convert these numbers to dates, find the difference between them and then get the minimum of all the results. I want the difference to be represented as days.
Any ideas how you do this?
Thanks very much :).
Well, Unix timestamps are expressed as a number of seconds since 01 Jan 1970, so if you subtract one from the other you get the difference in seconds. The difference in days is then simply a matter of dividing by the number of seconds in a day:
(date_modified - date_submitted) / (24*60*60)
or
(date_modified - date_submitted) / 86400
To convert UNIX time to a date you can use:
DATE '1970-01-01' + numtodsinterval(:unix_time_stamp, 'second')
In SQL when you substract two dates you will get the difference in days so you could write:
SELECT MIN(dt_mod - dt_sub)
FROM (SELECT DATE '1970-01-01'
+ numtodsinterval(m_bug_t.date_submitted, 'second') dt_sub,
DATE '1970-01-01'
+ numtodsinterval(m_bug_history_t.date_modified, 'second') dt_mod
FROM m_bug_t, m_bug_history_t
WHERE m_bug_t.id = m_bug_history_t.bug_id
AND field_name = 'status'
AND new_value = '100')
Of course as others have suggested you don't really need to do this DATE conversion, you could just substract your 2 timestamps (difference in seconds) and convert the result in days.

Resources