HSQLDB just time value in insert - hsqldb

We are using HSQLDB for JUnits, our production database is Oracle.
I have a table in which there is a field (type is timestamp in Oracle) that carries the information about some important time in day.
I wanted to prepare test data for JUnit in script, but I failed.
The basic idea I can do in Oracle DB is
SYSDATE - TRUNC(SYSDATE)
when I tried the same with CURRENT_TIME in HSQLDB I got error:
org.hsqldb.HsqlException: incompatible data type in conversion
the next idea I got was to add time to "empty date", tried:
DATE '0000-01-01'
but got
org.hsqldb.HsqlException: data exception: invalid datetime format
strange for DATE '2013-01-01' it works fine, maybe the initialia zeros are the problem...no they are not, same for DATE '0-01-01'...
In this phase I was kind of mad already (think I can do in Oracle in a second and I spent several hours here).
From documentation I tried to find some combination of functions that creates the required result, but unfortunately I found that the documentation is not clear. It seems so for first read, but when tried I was surprised why this
DATEADD( 'hour', 1, CURRENT_DATE )
works fine, while
DATEADD( 'hour', 1, CURRENT_TIME)
ends with
org.hsqldb.HsqlException: incompatible data type in conversion
as opposite, DATE_ADD works for both and parameter type for both functions is the same in documentation :-/
I believe that I can do, something like
// 4x call of DATEADD, datetime not working as described above
date - years - months - days + seconds_from_midnight
but there have to be something simple to use (I hope so).
HSQLDB version: 2.3.1

Use this setting for your tests:
SET DATABASE SQL SYNTAX ORA TRUE
Then this works and returns an INTERVAL
SYSDATE - TRUNC(SYSDATE)
The simpler form is CAST (SYSDATE AS TIME) to return the time part of SYSDATE, which you can convert to an interval.
This date DATE '0000-01-01' is not accepted as there is no YEAR 0. You need to use DATE '0001-01-01'
This works fine to convert the time of the day into an INTERVAL:
LOCALTIME - TIME'00:00:00'
Note LOCALTIME has no time zone, while CURRENT_TIME has.

Related

converting Athena timestamp to date

I am running a query against Athena, and it breaks. Specifically, I get an error for the below fragment:
avg(
DATE_DIFF(
'minute',
CAST(from_iso8601_timestamp("sessions_staging".session_start_at) AS TIMESTAMP),
CASE
WHEN CAST("sessions_staging__end_raw" AS TIMESTAMP) + INTERVAL '1' MINUTE > CAST("sessions_staging".next_session_start_at AS TIMESTAMP) THEN CAST("sessions_staging".next_session_start_at AS TIMESTAMP)
ELSE CAST("sessions_staging__end_raw" AS TIMESTAMP) + INTERVAL '30' MINUTE
END
)
) "sessions_staging__average_duration_minutes"
Athena complains with Value cannot be cast to timestamp: 2022-08-03T00:05:54.300Z.
I tried a bunch of tricks like casting my date to string then casting again to a time or a timestamp type. A similar problem caused by the same issue is covered some in converting to timestamp with time zone failed on Athena
The value seems to be just fine. I am able to execute: SELECT CAST(From_iso8601_timestamp('2022-08-03T00:05:54.300Z') AS timestamp). If I do not use CAST() and just do: "sessions_staging".session_start_at, it says that (varchar(6), varchar, timestamp) for function date_diff so I know that session_start_at is perceived as VARCHAR.
However, for the type of casting described as a solution to my issue to work, in the linked discussion, SELECT need to be used, it seems. Everything that I tried including string manipulations did not work.
How could I re-write my query/casts for Athena to process my request?
I ended up with:
CAST(DATE_PARSE(my_varchar_date, '%Y-%m-%dT%H:%i:%s.%f%z') AS TIMESTAMP)

SQL - how to change the format of a current_timestamp to have 'mm ss' as zeros?

I want to check if a metric is still missing 4 hours later and return a single record if it exists. I wrote a query that checks if there were metrics in the last 4 hours. But I need to check if there is a metric for a certain hour that was expected to load 4 hours before.
-- Returns records that appeared within the last 4 hours
select * from main.basic_metrics
where metric_name = 'common_metric'
and transaction_time > current_timestamp - interval 4 hours
The problem is that transaction_timeis in the following format 2019-10-30T12:00:00.000+0000 where mm ss are always zeros. So when I check it like transaction_time = current_timestamp - interval 4 hours it returns nothing since current_timestamp contains mm ss data.
How should I format timestamp to the format similar to transaction_time - 2019-10-30T12:00:00.000+0000 ?
UPD: There was a typo, mentioned in the comments below. fixed it
That should be very simple: cast the string to timestamp with time zone:
WHERE CAST(transaction_time AS timestamp with time zone)
> current_timestamp - INTERVAL '4 hours'
Try the following:
select * from main.basic_metrics
where metric_name = 'common_metric'
and transaction_time = date_trunc('hour',current_timestamp) - interval 4 hours
This is not necessarily the best query for what you're doing, but it does solve the problem you're having. My guess is that some version of "between" or > and < would solve it, however without knowing exactly how the "transaction time" is populated, I'm could only venture guesses.
The trick in my example is to "truncate" everything after the "hours" off of the current_timestamp using date_trunc()
Note: It helps a lot to realize that timestamps are NOT formatted. Timestamps are a single long integer field that happens to get formatted on your screen so you can make sense of it. Text comparisons are nearly always the wrong way to do things, and datetime aware functions are the preferred method of doing any comparison.

google bigquery select from a timestamp column between now and n days ago

I have a dataset in bigquery with a TIMESTAMP column "register_date" (sample value "2017-11-19 22:45:05.000 UTC" ).
I need to filter records based on x days or weeks before today criteria.
Example query
select all records which are 2 weeks old.
Currently I have this query (which I feel like a kind of hack) that works and returns the correct results
SELECT * FROM `my-pj.my_dataset.sample_table`
WHERE
(SELECT
CAST(DATE(register_date) AS DATE)) BETWEEN DATE_ADD(CURRENT_DATE(), INTERVAL -150 DAY)
AND CURRENT_DATE()
LIMIT 10
My question is do I have to use all that CASTing stuff on a TIMESTAMP column (which seems like over complicating the otherwise simple query)?
If I remove the CASting part, my query doesn't run and returns error.
Here is my simplified query
SELECT
*
FROM
`my-pj.my_dataset.sample_table`
WHERE
register_date BETWEEN DATE_ADD(CURRENT_DATE(), INTERVAL -150 DAY)
AND CURRENT_DATE()
LIMIT
10
that results into an error
Query Failed
Error: No matching signature for operator BETWEEN for argument types: TIMESTAMP, DATE, DATE. Supported signature: (ANY) BETWEEN (ANY) AND (ANY) at [6:17]
any insight is highly appreciated.
Use timestamp functions:
SELECT t.*
FROM `my-pj.my_dataset.sample_table` t
WHERE register_date BETWEEN TIMESTAMP_ADD(CURRENT_TIMESTAMP(), INTERVAL -150 DAY) AND CURRENT_TIMESTAMP()
LIMIT 10;
BigQuery has three data types for date/time values: date, datetime, and timestamp. These are not mutually interchangeable. The basic idea is:
Dates have no time component and no timezone.
Datetimes have a time component and no timezone.
Timestamp has both a time component and a timezone. In fact, it represents the value in UTC.
INTERVAL values are defined in gcp documentation
Conversion between the different values is not automatic. Your error message suggests that register_date is really stored as a Timestamp.
One caveat (from personal experience): the definition of day is based on UTC. This is not much of an issue if you are in London. It can be a bigger issue if you are in another time zone and you want the definition of "day" to be based on the local time zone. If that is an issue for you, ask another question.

Timestamp query to hours

I need some help with timestamps with postgresql. I have a column for the timestamp with timezone named download_at for when a user downloaded an app and a column user_id which is an integer. I am trying to extract user IDs of users that have downloaded within the last 168 hours from the last 60 days of information. I am a bit confused on how I can approach this and felt stuck because of the two different times. I believe I might have to play around with the trunc function but felt a bit stuck.
A basic example:
SELECT *
FROM table1
WHERE download_at > now() - '186 hours'::interval
Postgres is phenomenal at handling dates and times. A breakdown of what this does:
now() --function that returns the current time as a datetime object
'186 hours'::interval --a string cast to an interval
In postgres :: does casting. When casting to an interval Postgres will turn formatted English to an interval object. Since you can subtract datetime and interval objects it'll do the rest for you.

BQ Date_ADD bug

I notice that if i minus 5 hours with date_add function - it's not take the date one day back
if it's should like this example
however if i wrapped it with date function so than it's showing the correct date.
select
DATE_ADD(timestamp('2014-10-26 04:00:00'), -5, "HOUR") as est_timstamp,
date(DATE_ADD(timestamp('2014-10-26 04:00:00'), -5, "HOUR")) as est_date
I will be glade to hear how can use Date_Add and still remain with timestamp type
and the day is moving back.
OK I think I know what is happening.
The query is returning a UTC timestamp. However, the BigQuery Web UI is rendering that timestamp in your timezone. One way to get around this would be to cast the timestamp to a string.