Difference in minutes from datetime - sql

I'm trying to obtain the total amount of time difference from two timestamp columns (datetime)
I currently have a Table 1 setup like the following:
Time_Line_Down => datetime
Time_Line_Ran => datetime
Total_Downtime => Computed column with formula:
(case when [Time_Line_Down] IS NULL then NULL else CONVERT([varchar],case when [Time_Line_Ran] IS NULL then NULL else [Time_Line_Ran]-[Time_Line_Down] end,(108)) end)
Every time some conditions occur, I am copying those three columns (I have more columns but the problem is on this ones) into another Table 2 originally setup like the following:
Time_Line_Down => datetime
Time_Line_Ran => datetime
Total_Downtime => datetime
I then use an excel spreadsheet to "Get External Data" from SQL Server and use a pivot table to work with the data.
Example
Time_Line_Down = 2015-02-20 12:32:40.000
Time_Line_Ran = 2015-02-20 12:34:40.000
Total_Downtime = 1900-01-01 00:02:00.000
Desired Output
I want the pivot table to be able to give me a Grand Total of downtime from all rows in that table
Let's say it was forty five hours, fifty minutes and thirty seconds of accumulated downtime it should read like (45:50:30)
The problem:
Even if I format the Total_Downtime column in the excel pivot table as h:mm:ss to read like this:
Total_Downtime = 0:02:00
As rows accumulate and the Grand Total is calculated the "Date" part of the timestamp is messing the result is the total exceeds 24 hours
What I have tried
I changed the data type format of column Total_Downtime in Table 2 to time(0) so that it won't send the "Date" part, only the "Time" part of the timestamp, it is working and reads out 00:02:00
But now all the values in my pivot table on excel for that column are 0:00:00 no matter what value is actually in the SQL table.
Any suggestions?

You can use the Excel time format [h]:mm:ss which can go beyond 24 hours.
Alternatively, you can use the SQL function DATEDIFF to get the total downtime in seconds, and then convert that to however you need to display it in Excel, e.g.
case when [Time_Line_Down] IS NULL then NULL else case when [Time_Line_Ran] IS NULL then NULL else datediff(ss, Time_Line_Ran, Time_Line_Down) end end
I don't think you need the CASE statements here, you can just use
datediff(ss, Time_Line_Ran, Time_Line_Down)

Thank you all for your help,
I went ahead an tried the function DATEDIFF as suggested, I changed Table 1 computed column formula and Table 2 Total_Downtime column data type to int. Once imported into excel this numeric value needed some extra calculations.
In principle is the best answer and should work for anyone trying to calculate the difference from two timestamps, as mentioned before, is pretty straight forward.
But in my situation I needed to maintain two things:
1) The format 00:00:00 for the column Total_Downtime in Table 1, which changed to an integer value when using DATEDIFF
2) The pivot table Total_Downtime column format [h]:mm:ss (suggested by TobyLL) in excel, which required several calculations to convert from seconds
Solution
After learning that every time I copied from Table 1 to Table 2 the computed value (e.g. 00:02:00) changed to 1900-01-01 00:02:00.000 and that when imported to Excel it equaled to 1.001388889, I decided to force the "Date" part of the time stamp to be 1899-12-31 so that Excel would only calculate the Grand total in the pivot table with the "Time" (decimal) part.

Related

What is the fastest way to populate table with dates after certain day?

Let's assume that we have the following input parameters:
date [Date]
period [Integer]
The task is the following: build the table which has two columns: date and dayname.
So, if we have date = 2018-07-12 and period = 3 the table should look like this:
date |dayname
-------------------
2018-07-12|THURSDAY
2018-07-13|FRIDAY
2018-07-14|SATURDAY
My solution is the following:
select add_days(date, -1) into previousDay from "DUMMY";
for i in 1..:period do
select add_days(previousDay, i) into nextDay from "DUMMY";
:result.insert((nextDay, dayname(nextDay));
end for;
but I don't like the loop. I assume that it might be a problem in the performance if there are more complicated values that I want to put to result table.
What would be the better solution to achieve the target?
Running through a loop and inserting values one by one is most certainly the slowest possible option to accomplish the task.
Instead, you could use SAP HANA's time series feature.
With a statement like
SELECT to_date(GENERATED_PERIOD_START)
FROM SERIES_GENERATE_TIMESTAMP('INTERVAL 1 DAY', '01.01.0001', '31.12.9999')
you could generate a bounded range of valid dates with a given interval length.
In my tests using this approach brought the time to insert a set of dates from ca. 9 minutes down to 7 seconds...
I've written about that some time ago here and here if you want some more examples for that.
In those examples, I even included the use of series tables that allow for efficient compression of timestamp column values.
Series Data functions include SERIES_GENERATE_DATE which returns a set of values in date data format. So you don't have to bother to convert returned data into desired date format.
Here is a sample code
declare d int := 5;
declare dstart date := '01.01.2018';
SELECT generated_period_start FROM SERIES_GENERATE_DATE('INTERVAL 1 DAY', :dstart, add_days(:dstart, :d));

Subtract datetime from two columns and put result as integer in third

I have 2 datetime columns in a table and I want to subtract each row one from another and somehow put results in new 3rd column rows as int.
I know I have to use DATEFIFF somehow, but what confuses me even more how do I parse each row of a table (while loop perhaps)?
Thank you!
Example to go by from SQL 2008 assuming Date1Column and Date2Column are datetime fields. I gave a few examples showing delta between dates in minutes, days, months.
Select
,CAST(DATEDIFF(mi, Date1Column, Date2Column) as int) as 'DeltaMinutes'
,CAST(DATEDIFF(day, Date1Column, Date2Column) as int) as 'DeltaDays'
,ISNULL(DATEDIFF(MONTH, Date1Column, Date2Column), -9999) as 'LastSWAge'
From Table

Using SQL to retrieve records within a period

I have a column called DUEDATE in my table called table1 which is a date in the format CCYYMMDD (This is a db2 database).
I want to retrieve DUEDATE records "within X days" of ANYGIVENDATE, so for example within 3 days of ANYGIVENDATE could mean all DUEDATE records that match dates 3 days before and after ANYGIVENDATE.
Although I can provide a CCYYMMDD argument I am struggling to compose the query.
I'm guessing I need to retrieve records
WHERE [DUEDATE] = [ANYGIVENDATE ± X DAYS]
(in CCYYMMDD format) ?
If you stored DUEDATE as the proper DATE data type, the query would simply be
...where DUEDATE between ANYGIVENDATE - X days and ANYGIVENDATE + X days
As it is, you could convert your values to the DATE data type, something like:
...where date(timestamp_format(varchar_format(DUEDATE),'YYYYMMDD'))
between date(timestamp_format(varchar_format(ANYGIVENDATE),'YYYYMMDD')) - X days
and date(timestamp_format(varchar_format(ANYGIVENDATE),'YYYYMMDD')) + X days
which might hurt performance in some cases. On IBM System i (formerly known as AS/400) you might try
...where date(timestamp_format(varchar(DUEDATE),'YYYYMMDD'))
between date(timestamp_format(varchar(ANYGIVENDATE),'YYYYMMDD')) - X days
and date(timestamp_format(varchar(ANYGIVENDATE),'YYYYMMDD')) + X days
because VARCHAR_FORMAT() there is only applicable to datetime data types. Alternatively you can calculate the boundary dates in the application and provide two decimal values in the WHERE clause:
...where DUEDATE between GIVENSTARTDATE and GIVENENDDATE
You'll need to compare DATE to DATE, so the database column and the input parameter need to be converted.
Or better, you should pass a DATE parm value into the stored proc and eliminate conversion for that value.
Or pass it in as a DATE, subtract/add X DAYS to it, then convert those resulting date values to DECIMAL or NUMERIC and use them to compare against the database value. Given the improper definition of the database column, that's possibly the best choice.
It's not totally clear what "within X days" means.

how to convert a number to date in oracle sql developer

I have a excel format dataset that need to be imported to a table, one column is a date, but the data is stored in number format, such as 41275, when importing data, i tried to choose data format yyyy-mm-dd, it gives an error: not a valid month, also tried MM/DD/YYYY also error: day of month must be between 1 and last day of month. does anyone know what is this number and how can i convert it to a date format when importing it into the database?Thanks!
The expression (with respect to the Excel's leap year bug AmmoQ mentions) you are looking for is:
case
when yourNumberToBeImported <= 59 then date'1899-12-31' + yourNumberToBeImported
else date'1899-12-30' + yourNumberToBeImported
end
Then, you may either
Create a (global) temporary table in your Oracle DB, load your data from the Excel to the table and then reload the data from the temporary table to your target table with the above calculation included.
or you may
Load the data from the Excel to a persistent table in your Oracle DB and create a view over the persistent table which would contain the above calculation.
The number you got is the excel representation of a certain date ...
excel stores a date as the number of days, starting to count at a certain date ... to be precise:
1 = 1-JAN-1900
2 = 2-JAN-1900
...
30 = 30-JAN-1900
so, to get your excel number into an oracle date, you might want to try something like this...
to_date('1899-12-31','yyyy-mm-dd') + 41275

Date/Time data types and declaration in SQL Server

I would like to have a date and time column in my table. The main purpose of having these 2 columns is to be able to return query results like:
Number of treatments done in the period November 2011.
Number of people working in shifts between 00:01 and 08:00 hours.
I have two tables, which have the following attributes in them(among others):
Shift(day, month, year)
Treatment(start_time, date)
For the first table- Shift, query results need to return values in
terms of (ex: December 30,2012)
For the second table, start_time needs to have values like 0001 and
0800(as I mentioned above). While, date can return values like
'November 2011'.
Initially I thought using the date datatype for declaring each of the day/month/year/date variables would do the job. But this doesn't seem to work out. Should I use int, varchar and int respectively for day, month and year respectively? Also, since the date variable does not have component parts, will date datatype work here? Lastly, if I use timestamp data type for the start_time attribute, what should be the value I enter in the insert column- should it be 08:00:00?
I'm using SQL Server 2014.
Thank You for your help.
AFAIK it is better to use one column by type of DateTime instead of two columns which hold Date and Time separately.
Also you could simply query this column either by Date or Time by casting it to corresponding type :
DECLARE #ChangeDateTime AS DATETIME = '2012-12-09 16:07:43.937'
SELECT CAST(#ChangeDateTime AS DATE) AS [ChangeDate],
CAST(#ChangeDateTime AS TIME) AS [ChangeTime]
results to :
ChangeDate ChangeTime
---------- ----------------
2012-12-09 16:07:43.9370000