Pull data between 2 dates in redshift - date

I am trying to pull data from Redshift but cannot seem to make the date range work and I am constantly getting an error.
The column where the data is located is called "impression_time" in the impression_db table.
The date is in UNIX
Here is the query I am trying to pull:
SELECT
split_part((timestamp '1970-01-01'::date + impression_time * interval '1 second'), ' ',1) AS impression_time ,
FROM impression_db
WHERE impression_time >= '2021-09-01'
AND impression_time < '2021-10-01'

It would really be helpful if you posted the error message but here's what I postulate is happening.
I assume that the impression_time data type is a date or a timestamp based on the WHERE clause (could be string but I don't think so). Your are comparing impression_time to a string that looks like a date and relying on implicit casting to convert these for you.
With that assumption I see that you are multiplying impression_time by the time interval '1 second'. This multiplication only makes sense if impression_time is a numeric value. I expect that an implicit cast is again needed to convert impression_time to an epoch representation so that this multiplication can be done. Then you are taking this epoch time interval and adding it to the Unix base time, casting that to a timestamp, and then implicitly casting that to a string. Lastly you perform split_part on this string to get the date portion. All of this could be replaced by
impression_time::date::text AS impression_time
or am I misreading what you are doing?
Now as for what your error likely is - I suspect one of the many implicit castings is not happening or happening in a way that doesn't make sense to the rest of the query. The exact error message should point to where the issue is occurring.

Related

How to load time difference from psql to google data studio

I have a psql connection where one of the columns are sql intervals, as such:
However, to me it seems that this is interpreted in a text format:
I would like to convert these into the GDS equivalent of interval / timedelta / duration; However, I cannot seem to find a function that does that.
I am aware of the DATE_DIFF function, with which I can picture a workaround, pseudocode:
DATE_DIFF(DATE(1000, 01, 01), DATE(1000+avg_timedelta.regexmatchyear, 01+avg_timedelta.regexmatchmonth, 01 + avg_timedelta.regexmatchday)
However, it feels strange to me that there is no interval type in GDS, even if one of the function's output is an interval; but the docs don't say anything about converting to interval.
I made the workaround in SQL, I created a column that converts the interval into int< number of hours> with:
EXTRACT(
epoch
FROM
CTE.myInterval
) / 3600 AS timedelta_hours
This does not answer the underlying problem that in GDS you cannot easily convert to interval type. (which they call duration).

Difference between two timestamps as timestamp across multiple days

I have two timestamps and I would like to have a result with the difference between them. I found a similar question asked here but I have noticed that:
select
to_char(column1::timestamp - column2::timestamp, 'HH:MS:SS')
from
table
Gives me an incorrect return if these timestamps cross multiple days. I know that I can use EPOCH to work out the number of hours/days/minutes/seconds etc but my use case requires the result as a timestamp (or a string...anything not an interval!).
In the case of multiple days I would like to continue counting the hours, even if it should go past 24. This would allow results like:
36:55:01
I'd use the built-in date_part function (as previously described in an older thread: How to convert an interval like "1 day 01:30:00" into "25:30:00"?) but finally cast the result to the type you desire:
SELECT
from_date,
to_date,
to_date - from_date as date_diff_interval,
(date_part('epoch', to_date - from_date) * INTERVAL '1 second')::text as date_diff_text
from (
(select
'2018-01-01 04:03:06'::timestamp as from_date,
'2018-01-02 16:58:07'::timestamp as to_date)
) as dates;
This results in the following:
I'm currently unaware of any way to convert this interval into a timestamp and also not sure whether there is a use for it. You're still dealing with an interval and you'd need a point of reference in time to transform that interval into an actual timestamp.

Converting string timestamp into date

I have dates in a postgres database. The problem is they are stored in a string field and have values similar to: "1187222400000" (which would correspond to 07.08.2007).
I would like to convert them into readable dates usind some SQL to_date() expression or something similar but can't come up with the correct syntax to make it work.
There really isn't enough information here for a conclusion, so I propose this 'scientific-wild-ass-guess' to resolve your puzzle. :)
It appears this number is UNIX 'epoch time' in milliseconds. I'll show this example as if your string field had the arbitrary name, 'epoch_milli'. In postgresql you can convert it to a time stamp using this statement:
SELECT TIMESTAMP WITH TIME ZONE 'epoch' + epoch_milli * INTERVAL '1 millisecond';
or using this built-in postgresql function:
SELECT to_timestamp(epoch_milli / 1000)
either of which, for the example '1187222400000', produces the result
"2007-08-15 17:00:00-07"
You can do some of your own sleuthing with quite a few values selected similarly to this:
SELECT to_timestamp(epoch_milli/1000)::DATE
FROM (VALUES (1187222400000),(1194122400000)) AS val(epoch_milli);
"Well, bollocks, man. I just want the date." Point taken.
Simply cast the timestamp to a date to discard the excess bits:
SELECT to_timestamp(epoch_milli / 1000)::DATE
Of course its possible that this value is a conversion or is relative to some other value, hence the request for a second example data point.

Subtract between timestamp in Redshift

I found a weird thing. If a timestamp value subtract another, then Redshift will return an strange prefix. For example,
select table1.c_timestamp - table1.c_timestamp from table_1
Expect result should be ZERO or similar something, because these two timestamp values are same.
However, what I received is "5012369 years 4 mons", which I have no idea how does Redshift calculate the result.
Is there anyone can show me some clues?
Thanks
Contrary to the other answer,
Datediff doesn't exactly subtract, but rather counts the number of times the datepart chosen starts between the two timestamps.
datediff(second, '2018-04-10 00:00:00.001','2018-04-10 00:00:00.999')
>> 0
select datediff(second, '2018-04-10 00:00:00.999','2018-04-10 00:00:01.001')
>> 1
See: Datediff documentation
Edit: this is the way I found of how to perform the OP's task
SELECT
round(((EXTRACT('epoch' FROM TIMESTAMP '2018-05-27 09:59:59.999') - EXTRACT('epoch' FROM TIMESTAMP '2018-05-27 09:59:59.001'))*1000 + EXTRACT(millisecond FROM TIMESTAMP '2018-05-27 09:59:59.999') - EXTRACT(millisecond FROM TIMESTAMP '2018-05-27 09:59:59.001'))::real/1000)
The right way to subtract between datetimes is:
select datediff(seconds, table1.c_timestamp, table1.c_timestamp) from table_1
Of course, it doesn't make much sense to subtract a timestamp from itself, because that obviously returns 0, but I assume you just run that as a test.

TSQL Between 2 dates or >= and <=?

Morning experts. I have a very simple query that I can not seem to get working as it should.
I have a table that has invoiceNumber, CustNum, Datetime, and Grand_total
I want to pull all transactions between a set of dates in this example all transactions between 4/10/2014 and 4/23/2014. I was using:
SELECT Invoice_number
,CustNum
,DATETIME
,Grand_Total
FROM invoice_totals
WHERE custnum = '10014877'
AND DATETIME BETWEEN '2014-04-10'
AND '2014-04-23'
ORDER BY DATETIME DESC
I just realized if there are any dates on 4/23 that this does not show them.. I have tried to substuite using:
WHERE custnum = '10014877'
AND DATETIME >= '2014-04-10' AND DATETIME <='2014-04-23'
But it is still giving me the same results (ignoring any transactions that occured on 4/23)
the last record pulling up has a datetime stamp of 2014-04-22 12:26:08.000. There ARE 2 transactions on the 23'ed I am trying to include.
Thank you very much.
The part:
AND DATETIME <='2014-04-23'
is actually(according to TSQL):
AND DATETIME <='2014-04-23 00:00:000'
So you're quering from midnight and missing all the transactions from 00:01 to 23:59 on the 23rd.
Try:
AND DATETIME <='2014-04-23 23:59:999'
Or
AND DATETIME < '2014-04-24'
Both should include all the transactions for the day of the 23rd.
If you're working with continuous data, such as datetimes, it's usually better to switch to using a semi-open interval - an inclusive start date and an exclusive end date. Exclusive end dates are usually easier to calculate:
WHERE custnum = '10014877'
AND DATETIME >= '20140410' AND DATETIME <'20140424'
I've also switched to a safe, unambiguous date format.
The alternative, using <= or BETWEEN (which is just shorthand for a pair of >= and <= comparisons, so your two queries were identical) requires an inclusive end date. Which depending on the exact data type you're using may be 2014-04-23T23:59:59.997 or 2014-04-23T23:59:59.9999 or any number of other possibilities - if you get it wrong and overspecify the value, it'll get rounded to be 20140424 and then an inclusive comparison is incorrect.
And even if you get it right today, it's a pain to find all usage of this pattern if the data type of the column changes later.
BETWEEN is inclusive with respect to the boundaries.
However, I'm guessing that the type of your (poorly named) DATETIME field is .. DATETIME, so in the comparison, the date '2014-04-23' gets converted to a DATETIME as follows: '2014-04-23:00:000'. Thus, all records with DATETIME greater than that first moment on 04-23 are rejected.