BigQuery: extract SECOND from TIMESTAMP - sql

How can i run this query?
Error Message: No matching signature for function EXTRACT for argument types: DATE_TIME_PART FROM INT64. Supported signatures: EXTRACT(DATE_TIME_PART FROM DATE); EXTRACT(DATE_TIME_PART FROM TIMESTAMP [AT TIME ZONE STRING]); EXTRACT(DATE_TIME_PART FROM DATETIME); EXTRACT(DATE_TIME_PART FROM TIME) at [12:12]
They both give the same error message
WHERE EXTRACT( SECOND FROM event_timestamp )
- EXTRACT( SECOND FROM last_event) >= (60 * 10)
OR last_event IS NULL
WHERE EXTRACT( SECOND FROM event_timestamp AT TIME ZONE "UTC")
- EXTRACT( SECOND FROM last_event AT TIME ZONE "UTC") >= (60 * 10)
OR last_event IS NULL

use TIMESTAMP_MICROS()
WHERE EXTRACT( SECOND FROM TIMESTAMP_MICROS(event_timestamp))
- EXTRACT( SECOND FROM last_event) >= (60 * 10)
OR last_event IS NULL

If you want events that are more than 10 minutes from the previous timestamp, just use some arithmetic and comparisons:
where event_timestamp > last_event + (60 * 10 * 1000000) or
last_event is null
You are storing the timestamp as a microseconds value. You don't need to convert to another type.
If you really wanted to convert this to timestamp values, you could use:
where timestamp_micros(event_timestamp) > timestamp_add(timestamp_micros(last_event), interval 10 minute) or
last_event is null
In particular, you don't want to extract seconds. That value is always going to be between 0 and 59.

Related

get time series in 10 minutes of interval

I am generating one time-series from using below query.
SELECT date_trunc('min', dd):: TIMESTAMP WITHOUT TIME zone as time_ent
FROM generate_series ( timestamp '2021-12-09 06:34:37' + ((DATE_PART('min', timestamp '2021-12-09 06:34:37')::integer % 2) || ' minutes') :: INTERVAL
, '2021-12-10 06:34:37'::timestamp
, '20 min'::interval) dd
and it will give me output like below.
2021-12-09 06:34:00.000
2021-12-09 06:54:00.000
2021-12-09 07:14:00.000
2021-12-09 07:34:00.000
but I need output like.
2021-12-09 06:40:00.000
2021-12-09 07:00:00.000
2021-12-09 07:20:00.000
2021-12-09 07:40:00.000
currently, the time series hours depend upon the timestamp that I pass. in above it gives me mins like 34,54,14...but I want the mins like 40,00,20...it should not depend on the time I passed in query. I tried with timestamp '2021-12-09 06:34:37' + ((DATE_PART('min', timestamp '2021-12-09 06:34:37')::integer % 2) || ' minutes') :: INTERVAL but not any success.
Based on your description, I assumed that you want to create a series of timestamps for 00, 20, 40 minute at each hour until the next day.
select *
from (
select date_trunc('hour', current_timestamp) + i * interval '20 minutes' as ts
from generate_series(1, 24*3) as t(i)) t
where ts between current_timestamp and current_timestamp + interval '1 day'
The key idea here is to truncate the current_timestamp to 00 minute first. This becomes the start of the series. Then filter out the generated timestamps outside the range you want. You may need to adjust the second argument of generate_series function, depending on your requirement.
Or you can just generate a series of timestamp like the following:
select *
from (
select ts
from generate_series(
date_trunc('hour', current_timestamp),
current_timestamp + interval '1 day',
interval '20 minutes') as t(ts)) as t
where ts between current_timestamp and current_timestamp + interval '1 day'
Here, you still need to trunc your timestamp to hour first so the start of the series at 00 minute.

How to calculate average time when it is used TIME format in Bigquery?

I'm trying to get the AVG time, but the time format is not supported by the AVG function. I tried with CAST function, like in some posts were explained, but it seems doesn't work anyway. Thanks
WITH october_fall AS
(SELECT
start_station_name,
end_station_name,
start_station_id,
end_station_id,
EXTRACT (DATE FROM started_at) AS start_date,
EXTRACT(DAYOFWEEK FROM started_at) AS start_week_date,
EXTRACT (TIME FROM started_at) AS start_time,
EXTRACT (DATE FROM ended_at) AS end_date,
EXTRACT(DAYOFWEEK FROM ended_at) AS end_week_date,
EXTRACT (TIME FROM ended_at) AS end_time,
DATETIME_DIFF (ended_at,started_at, MINUTE) AS total_lenght,
member_casual
FROM
`ciclystic.cyclistic_seasonal_analysis.fall_202010` AS fall_analysis
ORDER BY
started_at DESC)
SELECT
COUNT (start_week_date) AS avg_start_1,
AVG (start_time) AS avg_start_time_1, ## here is where the problem start
member_casual
FROM
october_fall
WHERE
start_week_date = 1
GROUP BY
member_casual
Try below
SELECT
COUNT (start_week_date) AS avg_start_1,
TIME(
EXTRACT(hour FROM AVG(start_time - '0:0:0')),
EXTRACT(minute FROM AVG(start_time - '0:0:0')),
EXTRACT(second FROM AVG(start_time - '0:0:0'))
) as avg_start_time_1
member_casual
FROM
october_fall
WHERE
start_week_date = 1
GROUP BY
member_casual
Another option would be
SELECT
COUNT (start_week_date) AS avg_start_1,
PARSE_TIME('0-0 0 %H:%M:%E*S', '' || AVG(start_time - '0:0:0')) as avg_start_time_1
member_casual
FROM
october_fall
WHERE
start_week_date = 1
GROUP BY
member_casual
Because BigQuery cannot calc AVG on TIME type, you would see the error message if you tried to do so.
Instead you could calc AVG by INT64.
The time_ts is timestamp format.
I tried to use time_diff to calc the differences from time to "00:00:00", then I could get the seconds in FLOAT64 format and cast it to INT64 format.
I create a function secondToTime. It's pretty straightforward to calc hour / minute / second and parse back to time format.
For the date format, I think you could do it in the same way.
create temp function secondToTime (seconds INT64)
returns time
as (
PARSE_TIME (
"%H:%M:%S",
concat(
cast(seconds / 3600 as int),
":",
cast(mod(seconds, 3600) / 60 as int),
":",
mod(seconds, 60)
)
)
);
with october_fall as (
select
extract (date from time_ts) as start_date,
extract (time from time_ts) as start_time
from `bigquery-public-data.hacker_news.comments`
limit 10
) SELECT
avg(time_diff(start_time, time '00:00:00', second)),
secondToTime(
cast(avg(time_diff(start_time, time '00:00:00', second)) as INT64)
),
secondToTime(0),
secondToTime(60),
secondToTime(3601),
secondToTime(7265)
FROM october_fall
I know a few months have passed, but maybe someone else will be facing the same issue.
As for the section where the problem occurred, something like this worked for me and gave the average ride_length:
FORMAT_TIMESTAMP
('%T',
TIMESTAMP_SECONDS(CAST(AVG(TIME_DIFF(ride_length, '00:00:00', SECOND)) AS
INT64)))
AS avg_ride_length

Teradata timestamp subtraction with difference in minutes

select StartDatetime,EndDatetime,
(TRIM((COALESCE(CAST((CAST(EndDatetime AS TIME) - CAST(StartDatetime AS TIME) MINUTE(4)) AS INT),'')))) as TimeDiff
From Table1
EndDatetime and StartDatetime are columns of type Timestamp(6). The above query gave the difference in between the timestamps in minutes. It is working if both the timestamps are present in the same day. But when EndDatetime is having a value of tomorrow wrt to the StartDatetime then the TimeDiff value that is being returned is a negative value. Using absolute function is not a best solution because then the TimeDiff number itself isn't accurate.
How to get the timestamp difference precisely in minutes?
here is one way by using extract :
Select
StartDatetime,EndDatetime
,(CAST((CAST(EndDatetime AS DATE)- CAST(StartDatetime AS DATE)) AS DECIMAL(18,6)) * 60*24)
+ ((EXTRACT(HOUR FROM EndDatetime) - EXTRACT(HOUR FROM StartDatetime))* 60)
+ ((EXTRACT(MINUTE FROM EndDatetime) - EXTRACT(MINUTE FROM StartDatetime)))
+ ((EXTRACT(SECOND FROM EndDatetime) - EXTRACT(SECOND FROM StartDatetime))/60)
AS "Difference in Minutes"
from Table1

Add TIME to DATETIME value

I can see from documentation that DATETIME_ADD only works with INT64 values, not TIME objects.
I have a DATETIME which represents the point of start, and then a duration in a TIME object
WITH input AS (
SELECT
DATE(2018,03,05) AS start_date,
TIME(5,0,0) AS start_time,
TIME(8,0,0) AS duration
)
SELECT
*,
DATETIME(start_date,start_time) AS start_datetime,
DATETIME_ADD(
DATETIME_ADD(
DATETIME_ADD(
DATETIME(start_date,start_time),
INTERVAL EXTRACT(HOUR FROM duration) HOUR
),
INTERVAL EXTRACT(MINUTE FROM duration) MINUTE
),
INTERVAL EXTRACT(SECOND FROM duration) SECOND
) AS end_datetime
FROM input
Exists a nicer way to add the 3 values of the TIME object (hours ,minutes ,seconds) to the given DATETIME object?
Below is for BigQuery Standard SQL
WITH input AS (
SELECT
DATE(2018,03,05) AS start_date,
TIME(5,0,0) AS start_time,
TIME(8,0,0) AS duration
)
SELECT
*,
DATETIME(start_date,start_time) AS start_datetime,
DATETIME_ADD(
DATETIME_ADD(
DATETIME_ADD(
DATETIME(start_date,start_time),
INTERVAL EXTRACT(HOUR FROM duration) HOUR
),
INTERVAL EXTRACT(MINUTE FROM duration) MINUTE
),
INTERVAL EXTRACT(SECOND FROM duration) SECOND
) AS end_datetime,
DATETIME_ADD(
DATETIME(start_date,start_time),
INTERVAL DATETIME_DIFF(DATETIME(start_date,duration), DATETIME(start_date), SECOND) SECOND
) end_datetime_nicer_way
FROM input

SQL extract hour from timestamp

This query: select EXTRACT(HOUR FROM 1435047532) as hour from TABLENAME;
Returns this error: "invalid extract field for extract source".
I'm trying to extract the hour from a given timestamp. Maybe the problem is the format of timestamp field is NUMBER and not TIMESTAMP?
You can convert your numeric seconds-since-epoch time to a TIMESTAMP type using:
TIMESTAMP '1970-01-01 00:00:00' + NUMTODSINTERVAL( your_time_since_epoch, 'SECOND' )
So to get the hours:
SELECT EXTRACT( HOUR FROM TIMESTAMP '1970-01-01 00:00:00'
+ NUMTODSINTERVAL( 1435047532, 'SECOND' ) )
FROM DUAL;
If you need to handle leap seconds then you will need to create a function/package to handle this.
try this
select extract(hour from (select to_date('19700101', 'YYYYMMDD')
+ ( 1 / 24 / 60 / 60 ) * 1435047532 from dual)) from dual