How I can convert date to char and then ti number? - sql

Please help to sole this task. I need convert date to char and then to number, so that i can perform arithmetic operation and divide the date by 2.
select (sysdate+30+30+89)/2 from dual;
This query doesn't work and i have no idea how i can convert date to number.

The only sensible reason that I can think of for doing something like this is to get the midpoint of two dates, where one is sysdate.
If that is what you are trying to do, subtract the dates and divide by 2. Dividing an interval in half makes sense. Then add the resulting interval back to one of the dates.
For instance:
select date '2020-01-01' + (sysdate - date '2020-01-01') / 2
from dual

Based on the understanding of the question I think you need the current day of the year to perform arithmetic operation
SELECT (to_number(to_char(sysdate,'DDD'))+30+30+89)/2 from dual;

Related

How to calculate exact hours between two datetime fields?

I need to calculate hours between datetime fields and I can achieve it by simply doing
select date1,date2,(date1-date2) from table; --This gives answer in DD:HH:MM:SS format
select date1,date2,(trunc(date1)-trunc(date2))*24 --This doesn't take into account the time, it only gives hours between two dates.
Is there a way I can find the difference between date times that gives the output in Hours as a number?
The 'format' comment on your first query suggests your columns are timestamps, despite the dummy column names, as the result of subtracting two timestamps is an interval. Your second query is implicitly converting both timestamps to dates before subtracting them to get an answer as a number of days - which would be fractional if you weren't truncating them and thus losing the time portion.
You can extract the number of hours from the interval difference, and also 24 * the number of days if you expect it to exceed a day:
extract(day from (date1 - date2)) * 24 + extract(hour from (date1 - date2))
If you want to include fractional hours then you can extract and manipulate the minutes and seconds too.
You can also explicitly convert to dates, and truncate or floor after manipulation:
floor((cast(date1 as date) - cast(date2 as date)) * 24)
db<>fiddle demo
Use the DATEDIFF function in sql.
Example:
SELECT DATEDIFF(HOUR, '2021-09-05 12:00:00', GETDATE());
You can find it using the differnece of dates and multiplying with 24
select date1
,date2
,(date1-date2)*24 as diff_in_hrs
from table

Rolling 12 months oracle

I am writing a query in Oracle that I want to automate. I currently have a where clause that has the following:
TRAN.DATE BETWEEN 20160101 AND 20161231
I want the query to be a 12 month look back from the current date. I think I can do it if the date was in a date format using the following:
TRAN.DATE BETWEEN ADD_MONTHS(SYSDATE, -12) AND SYSDATE
But the date format in the table is in an integer format. I have tried to the TO_DATE function but I can't get the format right.
Yikes, you mean your database table literally has an integer of 20170104 (twenty million, one hundred seventy thousand, one hundred and four) and this represents the forth of Jan, this year?
Setting aside any concerns I have about this not being the best way to store a date, it's probably going to be easiest to write and also understand, if you convert your date to char and then to int:
WHERE DATECOLUMN BETWEEN
TO_NUMBER(TO_CHAR(ADD_MONTHS(SYSDATE,-12),'YYYYMMDD')) AND
TO_NUMBER(TO_CHAR(SYSDATE,'YYYYMMDD'))
There's no point getting clever and trying to deal with it as an integer math problem by subtracting 1200 or 10000 etc as a number because it'll make your query hard to understand and have no performance gain at all over a couple of number conversions as per this way
You'd be better off changing those dates to actual dates right now, before the codebase grows any bigger and someone decides it's a good idea to add more date columns stored as ints
You could try
TO_DATE(TRAN.DATE, 'YYYYMMDD') BETWEEN ADD_MONTHS(SYSDATE, -12) AND SYSDATE
According to Oracle documentation,
TO_DATE converts char of CHAR, VARCHAR2, NCHAR, or NVARCHAR2
datatype to a value of DATE datatype
so you need to first cast integer column to char or any of the accepted datatype specified above, and then cast it to DATE as below.
SELECT TO_DATE(to_char(20160101),'YYYYMMDD') as DATE1 FROM DUAL
Result
DATE1
-------------------
01.01.2016 00:00:00
so you need to rewrite your query as below.
TO_DATE(to_char(TRAN.DATE),'YYYYMMDD') BETWEEN ADD_MONTHS(SYSDATE, -12) AND SYSDATE
Also if you need only date part, you amy also need to trunc sysdate.
You can check the demo here
Hope this will help.

Substraction with decimal in ORACLE SQL

I need to substract 2 timestamps in the given format:
16/01/17 07:01:06,165000000
16/01/17 07:01:06,244000000
I want to express the result with 2 decimal values but somewhere in the CAST process I am loosing precision. My atempt by now goes this way:
select
id,
trunc((CAST(MAX(T.TIMESTAMP) AS DATE) - CAST(MIN(T.TIMESTAMP) AS DATE))*24*60*60,2) as result
from table T
group by id;
But I get id_1 '0' as a result for the two timestamps above even after I set the truncate decimals at 2.
Is there a way that I can obtain the 0.XX aa a result of the substraction?
It's because you are casting the timestamp to date.
Use to_timestamp to convert your string into timestamp.
Try this:
with your_table(tstamp) as (
select '16/01/17 07:01:06,165000000' from dual union all
select '16/01/17 07:01:06,244000000' from dual
),
your_table_casted as (
select to_timestamp(tstamp,'dd/mm/yy hh24:mi:ss,ff') tstamp from your_table
)
select trunc(sysdate + (max(tstamp) - min(tstamp)) * 86400 - sysdate, 2) diff
from your_table_casted;
The difference between two timestamps is INTERVAL DAY TO SECOND.
To convert it into seconds, use the above trick.
DATE—This datatype stores a date and a time, resolved to the second. It does not include the time zone. DATE is the oldest and most commonly used datatype for working with dates in Oracle applications.
TIMESTAMP—Time stamps are similar to dates, but with these two key distinctions: you can store and manipulate times resolved to the nearest billionth of a second (9 decimal places of precision), and you can associate a time zone with a time stamp, and Oracle Database will take that time zone into account when manipulating the time stamp.
The result of a substraction of two timestamps is an INTERVAL:
INTERVAL—Whereas DATE and TIMESTAMP record a specific point in time, INTERVAL records and computes a time duration. You can specify an interval in terms of years and months, or days and seconds.
You can find more information here

How to Round up timestamp to number of Days?

PreparedStatement psnmt=con.prepareStatement("SELECT (?)-(?) as DiffDate FROM dual");
psnmt.setTimestamp(1,ctenderdate);
psnmt.setTimestamp(2,btenderdate);
ResultSet resrt=psnmt.executeQuery();
if(!resrt.next())
{
out.println("No Records Found");
}
else
{
do
{
datediff=resrt.getString("DiffDate");
}
while(resrt.next());
System.out.println("the no of days Difference"+datediff);
}
ctenderdate=2015-06-27 00:00:00.0
btenderdate=2015-06-29 00:00:00.0
datediff=1 10:18:51.940000000
Expected datediff=2
How to round it off datediff to number of days
EDIT
Subtract TIMESTAMP values
If we really want to subtract two TIMESTAMP values, then we have to work with the INTERVAL DAY TO SECOND datatype that's returned. The easiest way to work with that is to use the EXTRACT function.
If want to return integer number of days (emulating the CEIL function) then we could test whether any part of the time (HOUR, MINUTE, SECOND) was non-zero. If they are all zero, we can use just the DAY portion. Otherwise, we have to add 1 to the DAY portion, and return that.
For example:
SELECT EXTRACT(DAY FROM diff.idts)
+ CASE
WHEN EXTRACT(HOUR FROM diff.idts) > 0
OR EXTRACT(MINUTE FROM diff.idts) > 0
OR EXTRACT(SECOND FROM diff.idts) > 0
THEN 1
ELSE 0
END
AS days_diff
FROM ( SELECT ? - ? AS idts FROM dual ) diff
ORIGINAL ANSWER
For Oracle database, you can perform this operation in the database:
SELECT CEIL(TO_DATE(?,'YYYY-MM-DD HH24:MI:SS.F')-TO_DATE(?,'YYYY-MM-DD HH24:MI:SS.F'))
FROM dual
This assumes the bind parameters are passed as strings, in format that matches the format model specified in the TO_DATE function, for example:
'2015-06-27 14:45:21.0'
(I'm assuming Oracle because of the use of the dual table, and because you are using subtraction operation between two dates. You would need a different statement for a different database.)
To unpack that expression a little bit...
The Oracle TO_DATE function converts a character string into an Oracle DATE value. The second argument is the format model, specifies that format of the first argument.
A subtraction operation between two DATE values returns the difference as a number of days (integer days plus fractional days.)
The CEIL function rounds a non-integer value up to the next higher integer.
FOLLOWUP
Q: how to use it with timestamp?
A: A subtraction of two TIMESTAMP values gets returned as an INTERVAL DAY TO SECOND datatype. And I'd prefer to avoid working with that.
In Oracle, when we do a subtraction of two DATE values, we get a decimal number. That's much easier to work with.
And in terms of "rounding" up a difference in days, I'm fine with disregarding fractional seconds.
If I had to pass in TIMESTAMP values, I would convert them to DATE values. The expressions above are already expecting string values, so I would just replace the ? with
TO_CHAR(?,'YYYY-MM-DD HH24:MI:SS')
If I had a requirement to pass in TIMESTAMP datatype, and return integer days difference rounded up, I would use a query like this:
SELECT CEIL( TO_DATE(TO_CHAR( ? ,'YYYY-MM-DD HH24:MI:SS'),'YYYY-MM-DD HH24:MI:SS')
- TO_DATE(TO_CHAR( ? ,'YYYY-MM-DD HH24:MI:SS'),'YYYY-MM-DD HH24:MI:SS')
) AS days_diff
FROM dual
Check out this link. There are answers for results in hours or minutes. What you are looking for should be similar.
My bad. I should not post just-a-link-answers. What you can do, as described there is:
SELECT TRUNC (SYSDATE) - TO_DATE ('10/20/2012', 'mm/dd/yyyy') FROM DUAL;
Notice the following details:
ENDDATE - STARTDATE will give you a number that corresponds to the
number of days between the two dates.
If you want the result in hours, multiply by 24; if minutes, multiply
by 24*60 and so forth.
You can also convert the result to an INTERVAL. There are two type of
intervals: NUMTODSINTERVAL(ENDDATE - STARTDATE, 'DAY') or
NUMTOYMINTERVAL(ENDDATE - STARTDATE, 'DAY')

In MonetDB, how can I get the date as an integer?

I want to be able to do something like
SELECT cast(my_date_col AS int) FROM my_table;
I would like to get the integer which MonetDB uses internally, i.e. the value you'd find if you looked into the BAT structure and got the appropriate element in code in MonetDB's GDK. Now, AFAICT, this internal value is the number of days since the Epoch, being Jan 1st on "Year 0" (so January 3rdt year 2 would be 366+365+2 = 732).
The best I could actually manage is
SELECT my_date_col AS int - cast('1-1-1' AS date) - 366 FROM my_table;
As MonetDB won't accept "Year zero" dates. This is rather an ugly hack, I'd like to do better. Help me?
If you're trying to get the number of days between "my_date_col" and 1970-01-01, in standard SQL you'd just subtract the one from the other. Your platform, monetdb, seems to support this syntax, but I don't have it installed. I wrote these examples in PostgreSQL.
select current_date - date '1970-01-01' as num_days;
num_days
--
16213
Check that result by adding 16213 days to the current date (2014-05-23).
select cast ((date '1970-01-01' + interval '16213' day) as date) as target_date
target_date
--
2014-05-23
The cast is necessary, because the result of this addition is a timestamp, not a date.
In your case, you want a column name instead of "current_date". So you're looking for something along these lines.
select my_date_col - date '1970-01-01' as num_days
from your-table-name;