Oracle sql: ORA-01830 when date calculation happens - sql

I want to perform following oracle SQL query
SELECT t1.Technology, count(t1.trax_id) as "Current number of items", to_char(to_date(max(round((SYSDATE - t1.time_event) * 24 * 60 * 60)),'sssss'),'hh24:mi:ss') as "max_ages"
from dm_procmon t1
group by t1.Technology;
The problem is the date substration formula.
I susbtract 2 dates from each other. This gives me a decimal value
(like 0,00855605). I want the value back to be a date value. So I
converted this first to a Number (Decimal > Number) and than to a
char (Number > Char) Finally from a char to date (Char > Date).
But when I perform the action I receive
Error report -
SQL Error: ORA-01830: Datumnotatieafbeelding eindigt voordat de gehele
invoerstring is geconverteerd.
01830. 00000 - "date format picture ends before converting entire input string"
What do I do wrong?

you try to convert to_date(%number of seconds%, 'sssss'), that is the problem. just use TO_CHAR(MAX(TO_DATE('20000101','yyyymmdd')+(SYSDATE - t1.time_event)),'hh24:mi:ss'); this will function correctly for intervals < 1day

here is a general solution without any limitations on maximum interval size:
select Technology, cnt as "Current number of items", FLOOR(x) || ':' || TO_CHAR(TO_DATE('20000101','yyyymmdd')+(x - FLOOR(x)),'hh24:mi:ss') as "max_ages"
from
(select t1.Technology, COUNT(t1.trax_id) cnt, MAX(SYSDATE - t1.time_event) x
from dm_procmon t1
group by t1.Technology);
FLOOR(x) returns the days and the rest (x - FLOOR(x)) is added to a constant date and transformed to hours, minutes and seconds

The following will give a DAY TO SECOND INTERVAL for all dates within about 68 years of one another:
SELECT t1.technology, COUNT(t1.trax_id) AS "Current number of items"
, NUMTODSINTERVAL(ROUND((SYSDATE - MIN(t1.time_event) * 24 * 60 * 60), 'SECOND') AS "max_ages"
FROM dm_procmon t1
GROUP BY t1.technology;
Note that rather that using MAX(SYSDATE - time), I used SYSDATE-MIN(time) (logically the same). The advantage of using this instead of TO_CHAR() is that you can then use the value returned in DATE/INTERVAL arithmetic.

Related

How to remove the decimals when Subtracting casted Dates (EPOCH) in SQL Developer

I am subtracting two epoch dates from each other to get a positive Integer that shows the number of days that has passed from creation to completion (aka modification).
Here is a snippet from my query, that accomplishes that from SQL Developer 20.2.0:
(TO_DATE('19700101', 'YYYYMMDD') + (DATEMODIFIED / 86400))-(TO_DATE('19700101', 'YYYYMMDD') + (DATECREATED / 86400)) AS "Age at Completion",
However, this results in an output of:
74.2922256787899889869
I don't need to see all those decimal places. A result such as this would be sufficient:
74.2922256787899889869 = 74
or
74.5922256787899889869 = 74
I think the ROUND function might be what I am looking for but I have no clue how to actually use it in that line. Can someone please assist? Thank you in advance.
(A + B) - (A + C) == A + B - A - C == B - C
So why not simply ROUND((DATECREATED - DATEMODIFIED) / 86400)?
Or maybe this:
DATEMODIFIED * INTERVAL '1' SECOND - DATECREATED * INTERVAL '1' SECOND
EXTRACT(DAY FROM (DATECREATED - DATEMODIFIED) * INTERVAL '1' SECOND)

SQL operand data type datetime / varchar is invalid for sum operator

I am trying to subtract one column from another column, and then sum the result. However, whatever I change I keep getting one of the two errors as mentioned in the title.
From all other questions posted, I derived that my statement should be something like:
SELECT SUM(EndTime-BeginTime) AS TotalTime FROM TimeRegister
WHERE OrderNumber = 00000 AND Activity = 11111;
As per suggestion in another topic, I changed the statement to:
SELECT SUM(CONVERT(varchar(EndTime-BeginTime), 108)) AS TotalTime FROM TimeRegister
WHERE OrderNumber = 00000 AND Activity = 11111;
However, I still receive the error.
The times are stored as follows:
1-1-1900 7:30:00
Thanks for any suggestion...
Edit 1: Oh, I am using a Microsoft Query through ODBC for SQL in Excel, kind of like:
Excel vlookup incorporating SQL table
Edit 2: I prefer to have the output again in the HH:MM format.
The thing is, when I copy the complete database to excel, everything works just fine. I can subtract the columns and sum up. I just dont want to that manually every day....
I just checked the SQL database, and the column is of Date/Time type.
First of all, trying to solve date or numeric issues by converting to text never solves anything, it adds additional problems like failed conversions or unexpected results.
SQL Server doesn't have a time interval type. If you subtract two datetime values you get back another datetime value that represents the difference as the offset since 1900-01-01. The following query :
select getdate() - dateadd(d,-1,getdate())
Will return :
1900-01-02 00:00:00.000
Which is 1 full day after 1900-01-01.
datetime values can't be summed though. SQL Server does have a time type but that just represents the time of day. Even if today - yesterday worked, converting that to time would return 00:00.
A quick solution is to use DATEDIFF to calculate the difference between two dates in whatever unit is required - hourss, minutes, seconds etc. Be aware though that DATEDIFF returns the number of interval boundaries crossed. DATEDIFF(DAY,...) between 11pm yesterday and 1am today will return 1, because 1 day boundary was crossed.
You can use
SELECT sum(datediff(minute,EndTime,BeginTime)) AS TotalMinutes
FROM TimeRegister
WHERE OrderNumber = 00000 AND Activity = 11111;
To calculate the difference in minutes and format it as a time interval on the client.
Another option is to cast the datetime to a float before summing, then back to datetime:
SELECT cast( sum(cast(EndTime - BeginTime as datetime)) as datetime) AS TotalOffset
FROM TimeRegister
WHERE OrderNumber = 00000 AND Activity = 11111;
A 2-day duration would appear as :
1900-01-03 00:00:00.000
This works because datetime can be cast to a float whose integral part represents the offset from 1900-01-01 and the fractional part the time.
A client written in a language like C# that does support intervals could subtract 1900-01-01 from this to get back the actual duration, eg :
TimeSpan duration = sumResult - new DateTime(1900,1,1);
Another option would be to avoid the final cast and just use the resulting float value as the number of days.
Displaying in Excel
The last option could be the easiest way to display the duration in Excel! Excel dates are actually stored as floats. What makes them appear as dates or times is the cell's formatting.
You can set a cells format to [h]:mm:ss to display any number as a duration. The [] is important - without it Excel will only display the time part of the "date".
If you enter 2 in a cell, h:mm:ss will show it as 0:00:00 while [h]:mm:ss will display 48:00:00, 48 hours.
Despite its strangeness,
SELECT sum(cast(EndTime - BeginTime as datetime)) AS TotalDuration
FROM TimeRegister
WHERE OrderNumber = 00000 AND Activity = 11111;
May be the best option to display a duration sum in Excel
You seem to want datediff():
SELECT SUM(DATEDIFF(second, BeginTime, EndTime) AS TotalTime
FROM TimeRegister
WHERE OrderNumber = 00000 AND Activity = 11111;
How about the following:
WITH totalTime AS (
SELECT SUM(DATEDIFF(second, EndTime, BeginTime)) as TimeInSecond
FROM TimeRegister
WHERE OrderNumber = 00000 AND Activity = 11111;
)
SELECT RIGHT('0' + CAST(TimeinSecond / 3600 AS VARCHAR),2) + ':' +
RIGHT('0' + CAST((TimeinSecond / 60) % 60 AS VARCHAR),2) + ':' +
RIGHT('0' + CAST(TimeinSecond % 60 AS VARCHAR),2) AS TimeElapsed
FROM totalTime;
In this solution, the time is converted into seconds, before being totalled, and then converted to HH:MM:SS.

SQL Command not properly ended ( oracle 11g for windows)

I m using this query to get a result of the difference between the start time and end time of an activity. Where the end time is null i wanted to put the minimum value as 500. Please advice and HELP!!
select * from table
where (end_time - start_time) * 24 * 60 > 1,
IF end_time IS NULL THEN '500';
So this is your query:
select * from table where (end_time - start_time) * 24 * 60 > 1;
But you want to treat a null end_time as 500. So use NVL or COALESCE to replace the null with 500:
select * from table where (nvl(end_time,500) - start_time) * 24 * 60 > 1;
IF end_time IS NULL THEN '500';
Just to make it more clear, '500' is not a number rather a string since it is enclosed within single quotation marks.
Now, end_time is. DATE data type or a timestamp, ideally. So, 500 makes no sense. You must convert it to appropriate type, whether 500 is days, hours, minutes, seconds, fraction of a second.
As in other answer it is suggested to use NVL(end_time, 500), it makes no sense. What does 500 - a date mean? Applying NVL is the need, however, you must convert it to the required value, else those are two different data types and Oracle won't allow it.
UPDATE
In my opinion,
Difference between two dates gives the number of days to the precision of seconds converted back to days. But, difference between an arbitrary number and a date makes no sense.
I assumed that start_time and end_time columns have number as datatype, for this calculation you need to select these specific columns and not all (*). Comparison is in where clause, this works in oracle11.
select ((NVL(END_TIME, 500)-START_TIME) * 24 * 60) from TABLE_NAME where ((NVL(END_TIME, 500)-START_TIME) * 24 * 60) > 1;

Division of dates to create percentage SQL

I am trying to do write in a function to subtract a few dates, then divide them together, add 1 then * 100 to get an overall % complete.
((SYSDATETIME() - proj.proj_scheduledDate)/(proj.proj_dueDate - proj.proj_scheduledDate + 1)) * 100 as 'percent done
returns
Operand data type datetime is invalid for divide operator.
What do I need to do to get this query to work? THANKS!
Might I suggest using DATEDIFF() with dd for a day datepart -- you can easily get the percentage of days completed - or go to smaller datepart values if you need to.
Returns the count (signed integer) of the specified datepart
boundaries crossed between the specified startdate and enddate.
SELECT
FLOOR((DATEDIFF(NOW(), proj.proj_scheduledDate) / DATEDIFF(proj.proj_dueDate, proj.proj_scheduledDate)) * 100)
FROM
foo;

Teradata - Invalid Date supplied for FIELD

I'm trying to query a table that has a varchar(100) "VALUE" column. This column can hold anything from a letter, a number or, in this case, a date.
The date will always be entered in the table as 'YYYY-mm-dd'. However, when I run the following query:
select * from myTable
where VALUE = '2009-12-11' (Date, Format 'yyyy-mm-dd')
I receive the following error:
Invalid date supplied for myTable.VALUE.
Example of the value table:
(1,'122')
(2,'red')
(3,'2009-12-11')
Any ideas as to what might be causing this?
Thanks!
if the data type is declared as varchar, it should just treat it like a string.
try not specifying anything about the date format, like
select * from myTable
where VALUE = '2009-12-11'
If you run an explain on the query, you can see that it's casting value to date before comparing against your supplied value. If you have another column that accurately records the type of what's in VALUE, you can add that to the where clause and you will no longer get the error (see below). Otherwise, go with Beth's recommendation.
select * from myTable
where VALUE = '2009-12-11' (Date, Format 'yyyy-mm-dd')
and VALUE_TYPE = 'DATE';
Teradata internal date calculation is (year - 1900) * 10000 + (month * 100) + day.
So if date is 02/11/2009 (2nd November 2010) then
=(2009-1900) * 10000 + (11 * 100) + 2
=109 * 10000 + 1100 + 2
=1090000 + 1100 + 2
=1090000
1100
2
----------
1091102
----------
So 2nd november 2009 is stored in Teradata as 1091102.
You can extract it in required format by casting (as u have it in varchar). Hope this helps.
Is it possible that VALUE is a reserved word in Teradata?
If so, you need to put that into double quotes:
select *
from myTable
where "VALUE" = '2009-12-11'