How to fetch data in a given interval in postgresql - 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"

Related

Certain Range of Date in each Month

I'd like to have a range of day 20th - 25th in each month in BigQuery but i dont know what syntax should i use. For ex:
Jan 20 - 25
Feb 20 - 25
and so on
I only can think of creating a CTE for every month then union all those.
Consider below query.
SELECT DATE_ADD(month, INTERVAL day - 1 DAY) date_range,
FROM UNNEST(GENERATE_DATE_ARRAY('2022-01-01', '2022-03-01', INTERVAL 1 MONTH)) month,
UNNEST(GENERATE_ARRAY(20, 25)) day;
Query results
Below seem to be more simple than my original answer and you could adjust date range by specifying condition on WHERE clause.
SELECT *
FROM UNNEST(GENERATE_DATE_ARRAY('2022-01-01', '2022-12-31', INTERVAL 1 DAY)) date_range
WHERE EXTRACT(DAY FROM date_range) BETWEEN 21 AND 25
For the usecase that you commented,
WHERE EXTRACT(DAY FROM date_range) >= 21 OR EXTRACT(DAY FROM date_range) = 1

Postgresql difference in time based on interval

I have a table, time_slots, which has a column start_time. My users table has a column, hours_before (int), which is the number of hours before the start_time to receive a notification.
I'm running a job every 5 minutes that checks the time slots that have a start_time which is now + hours_before. All my datetimes are store in UTC. I can't figure out the correct where clause to get the appropriate time slots.
Right now I'm passing in the current time in UTC as a string rather than doing something like current_timestamp at time zone 'UTC'.
(extract(epoch from starts_at) - extract(epoch from (date '2020-11-09 06:20:00' + (users.hours_before * INTERVAL '1 hour')))) = 0
Here is a test query to see what the values are inside of a select. In this example, (6 * INTERVAL '1 hour') would be where users.hours_before would be. I'm using a static 6 while tinkering.
select
(extract(epoch from "starts_at") - extract(epoch from date '2020-11-09 06:20:00')) / 3600 as hours,
(extract(epoch from "starts_at") - extract(epoch from (date '2020-11-09 06:20:00' + (6 * INTERVAL '1 hour')))) as other_interval,
*
from
"time_slots"
where
"starts_at" > '2020-11-09 06:20:00'
order by hours asc;
For example, the following query has the same hours and other_interval values as the above query, despite the date being 2020-11-09 10:00:00 instead of 2020-11-09 06:00:00. Shouldn't those columns be 4 hours different since they change by 4 hours?
select
(extract(epoch from "starts_at") - extract(epoch from date '2020-11-09 10:00:00')) / 3600 as hours,
(extract(epoch from "starts_at") - extract(epoch from (date '2020-11-09 10:00:00' + (6 * INTERVAL '1 hour')))) as other_interval,
*
from
"time_slots"
where
"starts_at" >= '2020-11-09 06:00:00'
order by hours asc;

Postgres range select between timestamps

Having two timestamps, and result in minutes between them lets say 320 minutes I need to calculate full hours, lets say we have here 5h and 20 minutes and I need to insert 6 rows with minutes column (5 rows with 60 as minutes column and last one with 20 minutes)
What is best way to do it in Postgres, some loops or trying to select numbers with cte?
demo:db<>fiddle
WITH timestamps AS (
SELECT '2019-01-07 03:30:00'::timestamp as ts1, '2019-01-07 08:50:00'::timestamp as ts2
)
SELECT 60 as minutes
FROM timestamps, generate_series(1, date_part('hour', ts2 - ts1)::int)
UNION ALL
SELECT date_part('minute', ts2 - ts1)::int
FROM timestamps
date_part extracts the hour (or minute) value from the timestamp difference.
with the generate_series function I am generating n rows with value 60 (n = hours)
Adding the remaining minutes with UNION ALL
Edit: For more than 1 day:
Instead of date_part use EXTRACT(EPOCH FROM ...) which gives you the difference in seconds.
WITH timestamps AS (
SELECT '2019-01-06 03:30:00'::timestamp as ts1, '2019-01-07 08:50:00'::timestamp as ts2
)
SELECT 60 as minutes
FROM timestamps, generate_series(1, (EXTRACT(EPOCH FROM ts2 - ts1) / 60 / 60)::int)
UNION ALL
SELECT (EXTRACT(EPOCH FROM ts2 - ts1) / 60)::int % 60
FROM timestamps
Calculate the seconds into hours with / 60 / 60
Calculate the remaining seconds with / 60 % 60 (first step gives you the minutes, the modulo operator % gives you the remaining minutes to hour)

postgresql query for hour minutes and seconds

Hi I am having a Postgresql query like below to calculate DateTime difference for {1} and {2} in minutes.
CAST(ROUND(EXTRACT(EPOCH from (({2}::timestamp) - ({1}::timestamp)))/60) AS INT)
I want to calculate the difference in hours, minutes and seconds displayed like:
3 hrs 31 minutes 42 secs
What manipulation do I need for displaying like above?
SELECT to_char((col1 - col0), 'HH24 hrs MI "minutes" SS "seconds"') FROM T1;
Here is a sqlfiddle : link
The to_char function takes an interval (an interval is the time span between two timestamps, and subtracting timestamps gives you an interval). It then takes a formatting, and you can apply pretty much what you want.
Formatting functions in PostgreSQL
Try use this sql:
SELECT to_char(column2 - column1, 'DD" days "HH24" hours "MI" minutes "SS" seconds"');
The subtraction of two timestamp or timestamptz values produces an interval. (While subtracting two date values produces an integer!)
Details about date/time types in the manual.
The default text representation of an interval may be sufficient:
SELECT timestamp '2017-1-6 12:34:56' - timestamp '2017-1-1 0:0';
Result is an interval, displayed as:
5 days 12:34:56
If you need the format in the question, precisely, you need to specify how to deal with intervals >= 24 hours. Add 'days'? Or just increase hours accordingly?
#Nobody provided how to use to_char(). But add days one way or the other:
SELECT to_char(ts_col2 - ts_col1, 'DD" days "HH24" hours "MI" minutes "SS" seconds"');
Result:
05 days 12 hours 34 minutes 56 seconds
'days' covers the rest. There are no greater time units in the result by default.
Simple
SELECT
EXTRACT(year FROM LOCALTIMESTAMP(0) - yourFieldTime)||' year '||
EXTRACT(month FROM LOCALTIMESTAMP(0) - yourFieldTime)||' month '||
EXTRACT(day FROM LOCALTIMESTAMP(0) - yourFieldTime)||' day '||
EXTRACT(hour FROM LOCALTIMESTAMP(0) - yourFieldTime)||' hour '||
EXTRACT(minute FROM LOCALTIMESTAMP(0) - yourFieldTime)||' minute '||
EXTRACT(second FROM LOCALTIMESTAMP(0) - yourFieldTime)||' second '
AS full_time_as_you_wish FROM your_table;
Result
full_time_as_you_wish
---------------------------------
0 year 0 month 0 day 0 hour 0 minute 0 second

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.