query to subtract date from systimestamp in oracle 11g - sql

I want to perform a subtraction operation on the date returned from another query and the system time in oracle SQL. So far I have been able to use the result of another query but when I try to subtract from systimestamp it gives me the following error
ORA-01722: invalid number
'01722. 00000 - "invalid number"
*Cause: The specified number was invalid.
*Action: Specify a valid number.
Below is my query
select round(to_number(systimestamp - e.last_time) * 24) as lag
from (
select ATTR_VALUE as last_time
from CONFIG
where ATTR_NAME='last_time'
and PROCESS_TYPE='new'
) e;
I have also tried this
select to_char(sys_extract_utc(systimestamp)-e.last_time,'YYYY-MM-DD HH24:MI:SS') as lag
from (
select ATTR_VALUE as last_time
from CONFIG
where ATTR_NAME='last_time'
and PROCESS_TYPE='new'
) e;
I want the difference between the time intervals to be in hours.
Thank you for any help in advance.
P.S. The datatype of ATTR_VALUE is VARCHAR2(150). A sample result of e.last_time is 2016-09-05 22:43:81796

"its VARCHAR2(150). That means I need to convert that to date"
ATTR_VALUE is a string so yes you need to convert it to the correct type before attempting to compare it with another datatype. Given your sample data the correct type would be timestamp, in which case your subquery should be:
(
select to_timestamp(ATTR_VALUE, 'yyyy-mm-dd hh24:mi:ss.ff5') as last_time
from CONFIG
where ATTR_NAME='last_time'
and PROCESS_TYPE='new'
)
The assumption is that your sample is representative of all the values in your CONFIG table for the given keys. If you have values in different formats your query will break on some other way: that's the danger of using this approach.

So finally after lots of trial and errors I got this one
1. Turns out initially the error was because the data_type of e.last_time was VARCHAR(150).
To find out the datatype of a given column in the table I used
desc <table_name>
which in my case was desc CONFIG
2. To convert VARCHAR to system time I have two options to_timestamp and to_date. If I use to_timestamp like
select round((systimestamp - to_timestamp(e.last_time,'YYYY-MM-DD HH24:MI:SSSSS')) * 24, 2) as lag
from (
select ATTR_VALUE as last_time
from CONFIG
where ATTR_NAME='last_time'
and PROCESS_TYPE='new'
) e;
I get an error that round expects NUMBER and got INTERVAL DAY TO SECONDS since the difference in date comes out to be like +41 13:55:20.663990. To convert that into hour would require a complex logic.
An alternative is to use to_data which I preferred and used it as
select round((sysdate - to_date(e.last_time,'YYYY-MM-DD HH24:MI:SSSSS')) * 24, 2) as lag
from (
select ATTR_VALUE as last_time
from CONFIG
where ATTR_NAME='last_time'
and PROCESS_TYPE='new'
) e;
This returns me the desired result i.e. the difference in hours rounded off to 2 floating digits

Related

What causes error "Strings cannot be added or subtracted in dialect 3"

I have the query:
WITH STAN_IND
AS (
SELECT ro.kod_stanow, ro.ind_wyrob||' - '||ro.LP_OPER INDEKS_OPERACJA, count(*) ILE_POWT
FROM M_REJ_OPERACJI ro
JOIN M_TABST st ON st.SYMBOL = ro.kod_stanow
WHERE (st.KOD_GRST starting with 'F' or (st.KOD_GRST starting with 'T') ) AND ro.DATA_WYKON>'NOW'-100
GROUP BY 1,2)
SELECT S.kod_stanow, count(*) ILE_INDEKS, SUM(ILE_POWT-1) POWTORZEN
from STAN_IND S
GROUP BY S.kod_stanow
ORDER BY ILE_INDEKS
That should be working, but I get an error:
SQL Error [335544606] [42000]: Dynamic SQL Error; expression evaluation not supported; Strings cannot be added or subtracted in dialect 3 [SQLState:42000, ISC error code:335544606]
I tried to cast it into bigger varchar but still no success. What is wrong here? Database is a Firebird 2.1
Your problem is 'NOW'-100. The literal 'NOW' is not a date/timestamp by itself, but a CHAR(3) literal. Only when compared to (or assigned to) a date or timestamp column will it be converted, and here the subtraction happens before that point. And the subtraction fails, because subtraction from a string literal is not defined.
Use CAST('NOW' as TIMESTAMP) - 100 or CURRENT_TIMESTAMP - 100 (or cast to DATE or use CURRENT_DATE if the column DATA_WYKON is a DATE).

CAST a calculation from dates into INT

I am learning BigQuery, and to practice I wanted to subtract a date from CURRENT_DATE (to calculate how many days since a last log in), but the result appears as a date.
I tried to CAST and SAFE_CAST but it gives me error.
# Gives calculaiton result as a date
SELECT
short_name,
CURRENT_DATE-last_log_in AS days_wo_log_in,
FROM `noted-wares-328320.demo.test_date`;
# Error invalid cast from INTERVAL to INT64
SELECT
short_name,
CAST (CURRENT_DATE-last_log_in as INT) AS days_wo_log_in,
FROM `noted-wares-328320.demo.test_date`;
Table that appears
Is there a way I am missing?
Thank you,
Use DATE_DIFF:
SELECT DATE_DIFF(CURRENT_DATE(), last_log_in, DAY) AS days_wo_log_in
FROM `noted-wares-328320.demo.test_date`;
Another approach
SELECT
short_name,
EXTRACT(DAY FROM CURRENT_DATE-last_log_in) AS days_wo_log_in
FROM `noted-wares-328320.demo.test_date`
with output

Using a subquery in the WHERE clause of gapfill in TimescaleDB

I would like to run the gapfill function of timescaleDB in a way, where the start and end dates are generated automatically. For example, I would like to run the gapfill function between the largest and the lowest entries in the database.
Given dataset playground:
CREATE TABLE public.playground (
value1 numeric,
"timestamp" bigint,
name "char"
);
INSERT INTO playground(name, value1, timestamp)
VALUES ('test', 100, 1599100000000000000);
INSERT INTO playground(name, value1, timestamp)
VALUES ('test', 100, 1599100001000000000);
INSERT INTO playground(name, value1, timestamp)
VALUES ('test', 100, 1599300000000000000);
I have tried getting the data as such:
SELECT time_bucket_gapfill(300E9::BIGINT, timestamp) as bucket
FROM playground
WHERE
timestamp >= (SELECT COALESCE(MIN(timestamp), 0) FROM playground)
AND
timestamp < (SELECT COALESCE(MAX(timestamp), 0) FROM playground)
GROUP BY bucket
I get an error:
ERROR: missing time_bucket_gapfill argument: could not infer start from WHERE clause
If I try the query with hard coded timestamps, the query runs just fine.
For example:
SELECT time_bucket_gapfill(300E9::BIGINT, timestamp) as bucket
FROM playground
WHERE timestamp >= 0 AND timestamp < 15900000000000000
GROUP BY bucket
Another approach of providing the start and end dates as arguments in the gapfill function fails as well.
WITH bounds AS (
SELECT COALESCE(MIN(timestamp), 0) as min, COALESCE(MAX(timestamp), 0) as max
FROM playground
WHERE timestamp >= 0 AND timestamp < 15900000000000000
),
gapfill as(
SELECT time_bucket_gapfill(300E9::BIGINT, timestamp, bounds.min, bounds.max) as bucket
FROM playground, bounds
GROUP BY bucket
)
select * from gapfill
ERROR: invalid time_bucket_gapfill argument: start must be a simple expression
time_bucket_gapfill only accepts start and finish values, which can be evaluated to constants at the query planning time. So it works to provide expression with constants and now, however it doesn't work to access a table in the expressions.
While this limitation on time_bucket_gapfill is in place it is not possible to achieve the desired behaviour in a single query. The work around is to calculate values for start and finish separately and then provide the values into the query with time_bucket_gapfill, which can be done in a stored procedure or in the application.
A side note, if PREPARE statement will be used in PostgreSQL 12, it is important to explicitly disable generic plan for the same reason.
for inferring start and stop from WHERE clause only direct column references are supported
see : https://github.com/timescale/timescaledb/issues/1345
so something like that might work , ( I have no timescaleDB access to test)
but try this :
SELECT
time_bucket_gapfill(300E9::BIGINT, time_range.min , time_range.max ) AS bucket
FROM
(
SELECT
COALESCE(MIN(timestamp), 0) AS min
, COALESCE(MAX(timestamp), 0) AS max
FROM
playground
) AS time_range
, playground
WHERE
timestamp >= time_range.min
AND timestamp < time_range.max
GROUP BY
bucket;

SQL query not returning data

I am trying to retrieve data from a Intersystems Cached database using a where clause with a timestamp, but nothing works.
Query:
select *
from dbo.iSkillsetStat
where Timestamp >= '2014-07-29 00:00:00'
Error:
ERROR: [SQLCODE: <-4>:<A term expected, beginning with one of
the following: identifier, constant, aggregate, %ALPHAUP, %EXACT,
%MVR, %SQLSTRING, %SQLUPPER, %STRING, %UPPER, $$, :,
+, -, (, NOT, EXISTS, or FOR>]
[Location: <Prepare>]
If I run the query without the timestamp all the data is returned.
Please any suggestions!
as TIMESTAMP is a reserved word, you should enclose it in double quotes "TIMESTAP"
In similar cases this worked for me:
select * from dbo.iSkillsetStat where Timestamp >= '2014-07-29T00:00:00'
Note the 'T' between the date and time values.
Try this:
select *
from dbo.iSkillsetStat
where Timestamp >= Convert(datetime, '2014-07-29 00:00:00')
Here you are missing 000 in your datetime 2014-07-29 00:00:00.
It should be like this 2014-07-29 00:00:00:000
instead of 2014-07-29 00:00:00
the field timestamp may be a reserved keyword and shouldn't be used for columnnames (have a look at https://www.drupal.org/node/141051 #728)
HINT:
if you field is of type TIMESTAMP convert the value before you compare it:
SELECT *
FROM dbo.iSkillsetStat
WHERE columnname >= TIMESTAMP('2014-07-29 00:00:00')

SQLite Order By Date1530019888000

Every record in my SQLite database contains a field which contains a Date stored as a string in the format 'yyyy-MM-dd HH:mm:ss'.
Is it possible to query the database to get the record which contains the most recent date please?
you can do it like this
SELECT * FROM Table ORDER BY date(dateColumn) DESC Limit 1
For me I had my query this way to solve my problem
select * from Table order by datetime(datetimeColumn) DESC LIMIT 1
Since I was storing it as datetime not date column
When you sure the format of text field is yyyy-MM-dd HH:mm:ss (ex.: 2017-01-02 16:02:55), So It works for me simply:
SELECT * FROM Table ORDER BY dateColumn DESC Limit 1
Without any extra date function!
You need to convert it to unix timestamp, and then compare them:
SELECT * FROM data ORDER BY strftime('%s', date_column) DESC
But this can be pretty slow, if there are lots of rows.
Better approach would be to store unix timestamp by default, and create an index for that column.
You can convert your column sent_date_time to yyyy-MM-dd format and then order by date:
1) substr(sent_date_time,7,4)||"-"||substr(sent_date_time,1,2)||"-"||substr(sent_date_time,4,2) as date
2) order by date desc
In my case everything works fine without casting column to type 'date'. Just by specifying column name with double quotes like that:
SELECT * FROM 'Repair' ORDER BY "Date" DESC;
I think SQLite makes casting by itself or something like that, but when I tried to 'cast' Date column by myself it's not worked. And there was no error messages.
You can also use the following query
"SELECT * FROM Table ORDER BY strftime('%Y-%m-%d %H:%M:%S'," + dateColumn + ") DESC Limit 1"
I found this ugly hack worked.
select *, substr(date_col_name,7,4)as yy,
substr(date_col_name,4,2) as mm,
substr(date_col_name,1,2) as dd
from my_table
order by yy desc,mm desc,dd desc
it would be better to convert the text column to date field type, but I found that did not work reliably for me.
If you do a lot of date sorting/comparison, you may get better results by storing time as ticks rather than strings, here is showing how to get 'now' in ticks with:
((strftime('%s', 'now') - strftime('%S', 'now') + strftime('%f', 'now')) * 1000)
(see https://stackoverflow.com/a/20478329/460084)
Then it's easy to sort, compare, etc ...
This will work for both date and time
SELECT *
FROM Table
ORDER BY
julianday(dateColumn)
DESC Limit 1