How to find the difference between two timestamp column - oracle

I have table name Record which has the following columns, Empid in number column, dat in timestamp
Which has the following values
empid dat
====== ====
101 4/9/2012 9:48:54 AM
101 4/9/2012 9:36:28 AM
101 4/9/2012 6:16:28 PM
101 4/10/2012 9:33:48 AM
101 4/10/2012 12:36:28 PM
101 4/10/2012 8:36:12 PM
101 4/11/2012 9:36:28 AM
101 4/11/2012 4:36:22 PM
Here I need to display the following columns,
empid,min(dat) as start,max(dat) as end and difference(max(dat)-min(dat) for each day
Here 3 different days are exists so It should return 3 records with the above mentioned columns.
Please give some ways to get this.

Simply subtract them: max(dat) - min(dat)
SELECT empid,
min(dat) as strt,
max(dat) as end,
max(dat) - min(dat) as diff
FROM the_table
GROUP BY empid;
If you want to group by the day instead of the empid, use this one:
select trunc(dat),
min(dat) as strt,
max(dat) as end,
max(dat) - min(dat) as diff
from the_table
group by trunc(dat)

Date arithmetic is pretty straightforward in Oracle: the difference betwwen two dates is returned as the number of days. Values of less than a day are returned as *decimals". That is, 75 minutes is 1.25 hours not 1.15. If you want it as hours and minutes you need to work with an interval.
The inner query calculates the difference between the minimum and maximum data for each employee for each day, and converts it to a DAY interval. The outer query extracts the HOUR and MINUTES from that interval.
select empid
, tday
, sdt
, edt
, extract(hour from diff) diff_hours
, extract (minute from diff) diff_minutes
from (
select empid
, trunc(dat) tday
, min(dat) sdt
, max(dat) edt
, numtodsinterval(max(dat) - min(dat), 'DAY') diff
from t42
group by empid, trunc(dat)
)

Related

Group by hour using Oracle SQL

I have a varchar5 column with times from
00:00
00:01
00:02
00:03
... all the way to
23:59
How would I count how many minutes are in an hour? To get the result
00 60
01 60
02 60
and so on...
SQL:
select 24_HOUR_CLOCK
From time table
Group by ...
Order by 24_HOUR_CLOCK ASC
Means to count records
I think you can use substr to extract first two characters from the time string and group on that.
select substr(col, 1, 2) hour, count(*) minutes
from your_table
group by substr(col, 1, 2)
order by hour
or find substr inside a subquery as #Mathguy suggested:
select hour,
count(*) minutes
from (
select substr(col, 1, 2) hour
from your_table
)
group by hour
order by hour

Divide time period into partitions and calculate averages

I have to divide elapsed time of a process into slots of equal sizes and calculate number of rows inserted during each time slot.
Here is DDL of the table
ID number
insert_date_time date
Sample Data
101 Aug 1 2015 4:43:00 PM
931 Aug 1 2015 4:43:01 PM
The output I am looking for is as follows
Time Slot Rows Inserted
4:00 pm - 5:00 pm 103
5:00 pm - 6:00 pm 95
6:00 pm - 7:00 pm 643
( I have left out date portion for brevity )
Similarly, I have to find out how much time each 100 rows took
0 - 100 rows 4:00pm - 4:43pm
101 - 200 rows 4:43pm - 5:58pm
I know Oracle OLAP functions can be used for this, but not sure how ?
Hoping I understood your requirement.
First Req#:
SELECT TO_CHAR(INSERT_TIME,'HH24'),COUNT(*) FROM TABLE
GROUP BY TO_CHAR(INSERT_TIME,'HH24');
Second Req#:
SELECT ROUND((ROW_NUMBER-1)/100,0),
MIN(INSERT_TIME) +'-'+ MAX(INSERT_TIME)
FROM TABLE
GROUP BY ROUND((ROW_NUMBER-1)/100,0);
If you are looking for 1 hour partitions, you can simply truncate the date column you are looking at to the hour trunc(your_date_col, 'hour') using that truncated value in your grouping clause.
For the 2nd requirement you can partition your rows with a query like this:
with data as (
select a.your_date_col
, row_number() over (order by Your_Date_Col) rn
, row_number() over (order by Your_Date_Col) -
mod(row_number() over (order by Your_Date_Col)-1,50) grp
from your_table a
)
select min(rn) ||' - '
||max(rn) ||' rows' rows
, min(your_date_col)||' - '
||max(your_date_col) time_range
from data
group by grp

select next record date minus 1 based on the logic

I want to achieve the following output through sql query
Below is the data in the oracle table
date 1 date 2 amt1 amt2
1/1/2012 12/31/2012 100 100
1/1/2013 11/31/2013 100 100
1/1/2014 9/31/2014 50 100
1/1/2015 12/31/2015 20 100
Desired output I need:
date 1 date 2 amt1 amt2
1/1/2012 12/31/2013 100 100
1/1/2014 12/31/2014 50 100
1/1/2015 12/31/9999 20 100
The logic to get the output would be if the amounts are same for multiple records then a single record should exist in the output with the earliest date as date1 . date 2 of the record written to the output should be next record effective date minus 1 , and if there is no next record found ,the date 2 should be defaulted to 31-dec-9999
(Note:whenever there is a change in amt1 or amt 2 between 2 records, those should be treated as separate records and if amts are same for all records then a single record should exist in the output )
Please let me know how to achieve this output through sql query
This solution uses a sub-query to aggregate a single row for each permutation of AMT1 and AMt2. Then it applies an analytic LEAD() function to get the next DATE1 and manipulates it according to the specification.
with yt as (
select amt1
, amt2
, min(date1) as date1
, max(date2) as date2
from your_table
group by amt1
, amt2
)
select yt.date1
, nvl(lead(yt.date1) over (order by yt.date1)-1, date '9999-12-31') as date2
, amt1
, amt2
from yt
order by yt.date1
/
By the way I had to correct your data (bad dates) when I used it in the inevitable SQL Fiddle; find it here.

Oracle Max Timetamp- subtract 45 minutes

I would like to build a query, which returns all records 45 Minutes before the max timestamp.
For example the record with the latest timestamp is:
01.09.2013 11:00:00
Now I would like to have all records from
01.09.2013 10:15:00 to 11:00:00
You can accomplish this by using Max aggregate/analytic function and interval statement:
Here is an example:
select col
from ( select col
, max(col) over() as max_time
from t1) t
where t.col between t.max_time - interval '45' minute
and t.max_time
Result:
Col
--------------------
01.09.13 11:00:00 AM
01.09.13 10:45:00 AM
01.09.13 10:30:00 AM
01.09.13 10:15:00 AM
SQLFiddle Demo
with cte as
(select max(the_timestamp_field) the_timestamp_field
from test)
select
*
from
test,cte
where
test.the_timestamp_field between cte.the_timestamp_field - (1/24*.75)
and cte.the_timestamp_field
will do it.
It can be simple and a little complicated, depending on how do you want to determine the creation time of the record. If there is a date column in your table which indicates the creation time it's simple:
SELECT columns
FROM table
WHERE date_column BETWEEN TO_DATE ('01.09.2013 10:15', 'MM.DD.YYYY HH24:MI') AND
TO_DATE('01.09.2013 11:00', 'MM.DD.YYYY HH24:MI')
If there is no date column you can use SCN_TO_TIMESTAMP(ORA_ROWSCN) pseudo column to determine the creation time, but please note that this feture requires 10g or greater version.

Unique rows in oracle 11g

I have a query which returns a set of records as like the one below:-
Date Dept commission
5-Apr Sales 20
4-Apr Sales 21
1-Jan Marketing 35
case 1: If i run a query between 1 Jan and 5 april I should get
Date Dept commission
5 April Sales 76
case 2: and when I run the query between jan 1 and jan 31 should get the output as
Date Dept commission
1 Jan Marketing 35
Case 2 is simple as when i put hte date range getting the required results , but not sure how to handle case 1 to show the max / latest date , the Dept for that date and a sum of the commission for that Dept , date for the selected date range . The output will be a single row with the latest date and department with a sum(commission) for the selected date range.
SELECT
MAX(Date) AS Date
, ( SELECT tt.Dept
FROM tableX tt
WHERE tt.Date = MAX(t.Date)
) AS Dept
, SUM(Commission) AS Commission
FROM
tableX t
WHERE
Date BETWEEN StartDate AND EndDate
The above works in SQL-Server, MySQL, Postgres as the sql-fiddle, test-1 shows, however it does NOT work in Oracle 11g R2 !
This works though (sql-fiddle, test-2):
SELECT
MAX(t.Date) AS Date
, MIN(tt.Dept) AS Dept --- MIN, MAX irrelevant
, SUM(t.Commission) AS Commission
FROM
( SELECT
MAX(Date) AS Date
, SUM(Commission) AS Commission
FROM
tableX
WHERE
Date BETWEEN StartDate AND EndDate
) t
JOIN
tableX tt
ON tt.Date = t.Date
The MIN(tt.Dept) is used to take care of the case you have more than row with the maximum date, say one row with Sales and one with Marketing, both in Apr-5
This works, too, using the LAST_VALUE analytic function (sql-fiddle, test-3):
SELECT
MAX(Date) AS Date
, MIN(Dept) AS Dept
, SUM(Commission) AS Commission
FROM
( SELECT
Date AS Date
, LAST_VALUE(Dept) OVER( ORDER BY Date
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
) AS Dept
, Commission AS Commission
FROM
tableX
WHERE
Date BETWEEN StartDate AND EndDate
) t

Resources