Calculate total seconds of time intervals - tsql

Considering a table that contain informations with time intervals like this:
ID StartTime EndTime
==================================================
1 2012-11-22 06:14:10 2012-11-22 06:18:00
2 2012-11-22 06:16:10 2012-11-22 06:19:40
3 2012-11-22 06:20:50 2012-11-22 06:21:20
4 2012-11-22 06:22:30 2012-11-22 06:23:00
5 2012-11-22 06:22:10 2012-11-22 06:24:40
..................................................
..................................................
The problem is find the better t-sql way for calculate total seconds of these intervals considering intersections time only one time.
For example, total seconds of the first three records is 360.

Here is an example, the script is finding the intervals where the seconds were not included in any rows and subtract it from the sum of the seconds between first 'start' and last 'end'. The script is assuming that the starttime is always smaller or equal to the endtime
select max(totalsec) - coalesce(sum(datediff(second, t.endtime, a.starttime)),0) from <table> t
cross apply
(select min(starttime) starttime from <table> where t.endtime < starttime) a
cross apply(select datediff(second, min(starttime), max(endtime)) totalsec from <table>) b
where
not exists (select 1 from <table> where id <> t.id and t.endtime >= starttime and t.endtime < endtime)

Related

How to fetch data in a given interval in postgresql

SELECT time,CEIL(AVG(value)) from table
where col1 = 1
and col2='matchThis'
and col3>='2022-04-10T18:30:00.00Z'
and col3<='2022-04-25T12:58:23.00Z'
and mod(to_char(col3, 'MI')::int, 15)=0
GROUP BY time
Semple response of the query to get 15-minute interval data
25-04-2022 01:00
25-04-2022 01:15
25-04-2022 01:30
25-04-2022 01:45
The above query works fine in 15, 30, and 60 minutes intervals but I have to create a query return interval data as the option shown below.
15 minutes
30 minutes
1 hour
2 hours
6 hours
12 hours
1 day
SELECT
ceil(avg(column_name)),
to_timestamp(floor((extract('epoch' from column_name) / 600 )) *600)
AT TIME ZONE 'UTC' as interval
FROM table_name
WHERE id=1
and column='value'
and col >='2022-04-21'
and col <= '2022-04-30'
GROUP BY interval ORDER BY interval ASC"

Count distinct dates between two timestamps

I want to count %days when a user was active. A query like this
select
a.id,
a.created_at,
CURRENT_DATE - a.created_at::date as days_since_registration,
NOW() as current_d
from public.accounts a where a.id = 3257
returns
id created_at days_since_registration current_d tot_active
3257 2022-04-01 22:59:00.000 1 2022-04-02 12:00:0.000 +0400 2
The person registered less than 24 hours ago (less than a day ago), but there are two distinct dates between the registration and now. Hence, if a user was active one hour before midnight and one hour after midnight, he is two days active in less than a day (active 200% of days)
What is the right way to count distinct dates and get 2 for a user, who registered at 23:00:00 two hours ago?
WITH cte as (
SELECT 42 as userID,'2022-04-01 23:00:00' as d
union
SELECT 42,'2022-04-02 01:00:00' as d
)
SELECT
userID,
count(d),
max(d)::date-min(d)::date+1 as NrOfDays,
count(d)/(max(d)::date-min(d)::date+1) *100 as PercentageOnline
FROM cte
GROUP BY userID;
output:
userid
count
nrofdays
percentageonline
42
2
2
100

Postgresql: how to add date and avoid weekend?

i have following table proses
id title created_at(Timestamp) slaTime(Integer)
1 Proses One 2012-11-22 13:50:09.924 4
2 Proses Two 2012-11-22 13:50:09.924 6
I want to find the deadline with calculation deadline = created_at + slaTime(No. of days). but it also avoid a weekend.
for example on id 1, 2012-11-22 is monday so the deadline is 2012-11-26 (friday)
but on id 2, the deadline should be 2012-11-30 (tuesday) not 2012-11-28(sunday)
You can use EXTRACT(DOW FROM timestamp) in order to define the day of the week as Sunday(0) to Saturday(6), and then add some extra days depending on the resulting day of the week :
SELECT CASE
WHEN d.curr_date = 0
THEN created_at + INTERVAL '1 day'
WHEN d.curr_date = 6
THEN created_at + INTERVAL '2 days'
ELSE created_at
END
FROM process
CROSS JOIN LATERAL (SELECT EXTRACT(DOW FROM (created_at :: date + slaTime)) AS curr_date) AS d

How to subtract seconds from postgres datetime without having to add it in group by clause?

Say I have column of type dateTime with value "2014-04-14 12:17:55.772" & I need to subtract seconds "2" seconds from it to get o/p like this "12:17:53".
userid EndDate seconds
--------------------------------------------------------
1 "2014-04-14 12:17:14.295" 512
1 "2014-04-14 12:31:14.295" 12
2 "2014-04-14 12:48:14.295" 2
2 "2014-04-14 13:22:14.295" 12
& the query is
select (enddate::timestamp - (seconds* interval '1 second')) seconds, userid
from user
group by userid
Now I need to group by userid only but enddate & seconds added to select query that is asking me to add it in group by clause which will not give me correct o/p.
I am expecting data in this format where I need to calculate start_time from end_time & total seconds spent.
user : 1
start_time end_time total (seconds)
"12:17" "12:17" 1
"12:22" "12:31" 512
total: 513
user : 2
"12:43" "12:48" 288
"13:22" "13:22" 1
total 289
Is there some way i could avoid group by clause in this?
Like #IMSoP says, you can use a window function to include a total for each user in your query output:
SELECT userid
, (enddate - (seconds * interval '1 second')) as start_time
, enddate as end_time
, seconds
, sum(seconds) OVER (PARTITION BY userid) as total
FROM so23063314.user;
Then you would only display the parts of the row you're interested in for each subtotal line, and display the total at the end of each block.

Retrieving the start and end hour queries correctly in PostgreSQL Query

I have a CTE-based query in which I retrieve hourly intervals between two given timespans. My query works as following:
Getting start and end datetimes (let's say 07-13-2011 00:21:09 and 07-31-2011 21:11:21)
get the hourly total query values between the hourly intervals (in here it's from 00 to 21, a total of 21 hours but this is parametric and depends on the hours I give for the inputs) for each day. This query works well but there is a problem. It displays hourly amounts but for the start time, it gets all the queries between 00:00:00 and 00:59:59 for each day instead of 00:21:09 - 00:59:59 and same applies for the end time, it gets all the queries between 21:00:00 and 22:00:00 for each day instead of 21:00:00 and 21:11:21. -By the way, the other hour intervals e.g 03:00 - 04:00 etc are currently retrieved normally, no minute and seconds provided, just 1 hour flat intervals- How can I fix that? The query is below, thanks.
WITH cal AS (
SELECT generate_series('2011-02-02 00:00:00'::timestamp , '2012-04-01 05:00:00'::timestamp , '1 hour'::interval) AS stamp
)
, qqq AS (
SELECT date_trunc('hour', calltime) AS stamp
, count(*) AS zcount
FROM mytable
WHERE calltime >= '07-13-2011 00:21:09' AND calltime <='07-31-2011 21:11:21' AND date_part('hour', calltime) >= 0 AND date_part('hour', calltime) <= 21
GROUP BY date_trunc('hour', calltime)
)
SELECT cal.stamp
, COALESCE (qqq.zcount, 0) AS zcount
FROM cal
LEFT JOIN qqq ON cal.stamp = qqq.stamp
WHERE cal.stamp >= '07-13-2011 00:00:00' AND cal.stamp<='07-31-2011 21:11:21' AND date_part('hour', cal.stamp) >= 0 AND date_part('hour', cal.stamp) <= 21
ORDER BY stamp ASC;
EDIT:
What I mean with my problem is, despite giving 00:21:09 for my starting hour on first day, the days after that day calculate the total query count for the first hour interval as count of total queries between 00:00:00-01:00:00 instead of 00:21:09-01:00:00.(by the way this should apply to the first hour interval for every day, I can give 04:30:21 for the starting hour and the day will start to count total queries hourly starting from there etc.- Same applies to the ending hour 21:00:00-21:11:21, only the LAST day in the query results take this interval, other days before it take the query count between hour 21 and 22 by counting all queries between 21:00:00-22:00:00 instead of 21:00:00-21:11:21.
For example, if there are 200 queries between 00:00:00 and 01:00:00 on july 14 2011 (the next day after july 13, the start date) but there are 159 queries between 00:21:09 - 01:00:00, I should get 159 queries instead of 200. Also, if there are 300 queries between 21:00:00-22:00:00 on any random day, and 123 of them are between 21:00:00-21:11:21, I should get 123 queries as result instead of 300. (This applies to every single day, other hourly intervals should be counted as usual such as 01:00-02:00, 20:00-21:00 etc. This is parametric, hourly intervals and start-end times depend on user input-
Adding AND calltime::time >= '00:21:09' AND calltime::time <= '21:11:21' to the WHERE calltime >= '07-13-2011 00:21:09' AND calltime <='07-31-2011 21:11:21' block solved the issue.