I am writing a query to convert a character to Date Time
The following query extracts my time stamps in Character format.
select
(to_char(TO_CHAR(MDY(month(current- 1 units month), 1,year(current- 1 units month)),'%Y-%m-%d')||' 13:00:00')),
(to_char(TO_CHAR((DATE(DATE(extend(TODAY, YEAR TO MONTH)) - 1 UNITS DAY)+1),'%d-%m-%Y')||' 13:00:00'))
from dual
Output:
`T 0÷
2015-08-01 13:00:00 01-09-2015 13:00:00
2015-08-01 13:00:00 01-09-2015 13:00:00
Now I am trying to convert the Character to Time stamp using DATETIME(2001-12-31 15:32:55) YEAR TO SECOND function. I am getting syntax error.
select
DATETIME(to_char(TO_CHAR(MDY(month(current- 1 units month), 1,year(current- 1 units month)),'%Y-%m-%d')||' 13:00:00')) YEAR TO SECOND ,
DATETIME(to_char(TO_CHAR((DATE(DATE(extend(TODAY, YEAR TO MONTH)) - 1 UNITS DAY)+1),'%d-%m-%Y')||' 13:00:00') ) YEAR TO SECOND
from dual
How ever the following is working fine:
select DATETIME(2001-12-31 15:32:55) YEAR TO SECOND
from dual
Thanks in Advance. Please do not suggest answers for Oracle. its damn easy in Oracle.
Try using a CAST to convert your output as a DATETIME YEAR TO SECOND:
select
(to_char(TO_CHAR(MDY(month(current- 1 units month), 1,year(current- 1 units month)),'%Y-%m-%d')||' 13:00:00'))::DATETIME YEAR TO SECOND ,
(to_char(TO_CHAR((DATE(DATE(extend(TODAY, YEAR TO MONTH)) - 1 UNITS DAY)+1),'%Y-%m-%d')||' 13:00:00'))::DATETIME YEAR TO SECOND
from dual
That seems to work OK, but I'd suggest you don't do this. Also, note that DATETIME is an ISO standard: YYYY-MM-DD HH:MM:SS.FFF (or part thereof). Your second example with the date in English format is not going to parse to a DATETIME.
Your first algorithm is not leap-day safe, and the second example is horribly over-complicated. You can determine 13:00 on the first day of the current month using the far simpler construction:
(TODAY-DAY(TODAY)+1)::DATETIME YEAR TO SECOND + INTERVAL(13) HOUR TO HOUR
This also has the benefit of avoiding casting back and forth between DATE and CHAR. The calculation of the same time the previous month can be written as:
MDY(MONTH(TODAY-DAY(TODAY)),1,YEAR(TODAY-DAY(TODAY)))::DATETIME YEAR TO SECOND + INTERVAL(13) HOUR TO HOUR
... which will do the right thing on Feb 29/March 1 in a leap year, which your algorithm won't.
The construction TODAY-DAY(TODAY) will always produce the last day of the prior month.
Related
I have below scenario that Business want to calculate Week Number based on Given Start Date to End Date.
For Ex: Start Date = 8/24/2020 End Date = 12/31/2020 ( These Start date & end date are not constant they may change from year to year )
Expected Output below:
[Date 1 Date 2 Week Number
8/24/2020 8/30/2020 week1
8/31/2020 9/6/2020 week2
9/7/2020 9/14/2020 week3
9/15/2020 9/21/2020 week4
9/22/2020 9/28/2020 week5
9/29/2020 10/5/2020 week6
10/6/2020 10/12/2020 week7
10/13/2020 10/19/2020 week8
10/20/2020 10/26/2020 week9
10/27/2020 11/02/2020 week10
11/03/2020 11/09/2020 week11
11/10/2020 11/16/2020 week12
11/17/2020 11/23/2020 week13
11/24/2020 11/30/2020 week14
I need Oracle Query to calculate Week Number(s) like above .. Based on Start date for 7 days then week number will be calcuated.. But remember that crossing months some month have 30 days and some month 31 days etc.. How to calculate ? Appreciate your help!!
Seems your looking for custom week definition rather that built-ins. But not overly difficult. The first thing is to convert from strings to dates (if columns actually coming off table this conversion is not required), and from there let Oracle do all the calculations as you can apply arithmetic operations to dates, except adding 2 dates. Oracle will automatically handle differing number of days per month correctly.
Two methods for this request:
Use a recursive CTE (with)
with dates(start_date,end_date) as
( select date '2020-08-24' start_date
, date '2020-12-31' end_date
from dual
)
, weeks (wk, wk_start, wk_end, e_date) as
( select 1, start_date, start_date+6 ld, end_date from dates
union all
select wk+1, wk_end+1, wk_end+7, e_date
from weeks
where wk_end<e_date
)
select wk, wk_start, wk_end from weeks;
Use Oracle connect by
with dates(start_date,end_date) as
( select date '2020-08-24' start_date
, date '2020-12-31' end_date
from dual
)
select level wk
, start_date+7*(level-1) wk_start
, start_date+6+7*(level-1)
from dates
connect by level <= ceil( (end_date-start_date)/7.0);
Depend on how strict you need to be with the end date specified you may need to adjust the last row returned. Both queries do not make adjust for that. They just ensure no week begins after that date. But the last week contains the full 7 days, which may end after the specified end date.
If your date datatype is varchar then first convert it to date and then convert it back to varchar.
convert date to to_char(to_date('8/24/2020','MM/DD/YYYY'),'WW')
If you to keep week datatype as a number then you can do something like this
to_number(to_char(to_date('8/24/2020','MM/DD/YYYY'),'WW'))
Few options according to your need.
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.
W Week of month (1-5) where week 1 starts on the first day of the month and ends on the seventh.
IW Week of year (1-52 or 1-53) based on the ISO standard.
I've got data from our third party partner and every date column is coded in this NUMBER(6,0) format:
118346
118347
118348
118351
119013
119035
119049
119051
118339
118353
119019
119028
119029
119031
None of the last 3 digits are more than 365, so I reckon 118339 must mean 2018 + 339 days, which is December 5, 2018: '2018-12-05'. I've never encountered this kind of format before, so I'm a bit helpless how to handle it. Is this some standardized format? Can I use some built-in convert function or should I just manually cut and convert it using some arithmetics?
I would like to sort my rows grouping by weeks, so maybe I shouldn't even convert it, but for some reason I feel converting to a date type would be more elegant. Which approach is the better?
EDIT: I've just checked my excel version of the data, and this format is in fact working as I've imagined. So the question stands.
This seems to be Excel's 1900-based internal representation of dates. Assuming your interpretation is right, you can convert to a normal date with a bit of manipulation:
-- CTE for sample values
with your_table (num) as (
select *
from table(sys.odcinumberlist(118339, 118346, 118347, 118348, 118351, 119013, 119035,
119049, 119051, 118339, 118353, 119019, 119028, 119029, 119031))
)
-- actual query
select num,
date '1899-12-31'
+ floor(num/1000) * interval '1' year
+ mod(num, 1000) * interval '1' day as converted
from your_table;
NUM CONVERTED
---------- ----------
118339 2018-12-05
118346 2018-12-12
118347 2018-12-13
118348 2018-12-14
118351 2018-12-17
119013 2019-01-13
119035 2019-02-04
119049 2019-02-18
119051 2019-02-20
118339 2018-12-05
118353 2018-12-19
119019 2019-01-19
119028 2019-01-28
119029 2019-01-29
119031 2019-01-31
This treats the first three digits - obtained with floor(num/1000) - as the number of years, offset from 1900. Those are multiplied by a single year interval value, to give 118 or 199 years. Then it treats the last three digits - from mod(num, 1000) - as the number of days into that year, by multiplying by a single day interval. Both are then added to the fixed date 1899-12-31. (You could use 1900-01-01 instead but then you have to subtract a day at the end...)
I am trying to round upwards to the nearest month. So far, I have:
SELECT ROUND(CURRENT_DATE, 'MM') FROM DUAL
Which rounds to the closest month, which is upwards in this case. At the time of posting, the output is 03/01/2019 in MM/DD/YYYY format.
But what if it's the first of a month for example?
SELECT ROUND(TO_DATE('01-03-19','DD-MM-YY'), 'MM') FROM DUAL
This produces the same output as above. But I am expecting 04/01/2019.
I could do something like:
SELECT TRUNC(ADD_MONTHS(TO_DATE('30-03-19','DD-MM-YY'),1), 'MM') - 1 FROM DUAL
Which produced the output 03/31/2019, which is as expected.
I take the 30th March, add one month onto it. Truncate that, to get the first day of that month, then just subtract one for the last day of the previous month.
Now this works, but it seems long and tedious. Surely there is a better way?
if you are trying to find last day of the current month
LAST_DAY(SYSDATE)
if you are trying to find first day of the next month
LAST_DAY(SYSDATE) + 1
I have a large data file containing a string type column 'YearMonthWeek'
It contains values such as '20160101' for the first week of January 2016, or '20161040' for the 40th week of the year 2016 apparently falling in October.
Now, I want to convert these strings to actual dates so that every YearMonthWeek value is converted to, say the first day of that week. (Whether that ends up being Monday or Sunday I don't really care).
I tried the following query:
PARSE_TIMESTAMP('%Y%m%W', CAST(YearMonthWeek AS STRING)) AS datefield
(See this documentation for details)
This runs without errors, but returns me the first day of the month for every single entry...
So for example '20160101' and '20160102' both get parsed as 2016-01-01 00:00:00 UTC.
Is this an issue with the PARSE_TIMESTAMP function, or am I missing something?
Try doing something like
DATE_ADD(date_expression, INTERVAL %W WEEK)
Static example:
SELECT
DATE_ADD(
DATE(PARSE_TIMESTAMP('%Y', SUBSTR(CAST('20161252' AS STRING),0,4))),
INTERVAL (CAST(SUBSTR(CAST('20160102' AS STRING),7) AS INT64)) week)
AS datefield
-
Row datefield
1 2016-01-15
You may add something as a margin to it, according to ISO 8601, the first week of the year is the one that contains January 4th. So you could have something like: 4 + 7*($week - 1)
I need to get the difference between 2 date time in minutes(Time difference in minutes). And the last difference will be calculated based on 6 PM of every date.
Sample data: need result of last column
User_Name Date Time difference in minutes
User 1 1/1/06 12:00 PM 30
user 2 1/1/06 12:30 PM 315
user 3 1/1/06 5:45 PM 15
Here the date will be always in same date and the last user date difference calculated based on default value 6PM. Assuming the dates of any user will not cross 6PM time.
Please suggest how to write the query for the same.
You could use the lead window function.
I assume your table is called mytable and the date column is mydate (it is a bad idea to call a column Date as it is a reserved word).
select user_name,
round((lead(mydate, 1, trunc(mydate)+18/24)
over (partition by trunc(mydate) order by mydate)
- mydate) *24*60) as difference
from mytable
I found the solution.. if its not correct let me know
SELECT User_name,created_date,
trunc(to_number((cast(nvl(lead (created_date,1) OVER (ORDER BY created_date),TRUNC(SYSDATE) + (19/24)) as date) - cast(created_date as date)))*24*60) as difference
FROM users;