Postgres Double Precision to Date - postgresql

I'm looking to cast/convert a decimal data into date data. I've looked online and am still struggling. Can you help? "value" is a double precision, and here I convert it to varchar. From that point on, I've tried using convert but I'm still unable to get a date value.
Thanks in advance!
select cast(value as varchar(8) )date_value, value,
For example: The value 43099 should read 12/30/2017.

Guessing from your meager example, you might want this:
SELECT date '1899-12-30' + 43099; -- returns date '2017-12-30'
You need to cast your value column to integer for this:
SELECT date '1899-12-30' + value::int;
Meaning, the number might represent the count of days since 1900 (with an off-by-2 error I can't explain).
Adding an integer to a date means adding the number of days.
If your value can have fractional digits, you can compute a timestamp in similar fashion:
SELECT timestamp '1899-12-30' + interval '1 day' * value;

Related

Convert integer to week interval

How one can convert integer to week interval?
CREATE TABLE integers( i integer);
INSERT INTO integers VALUES ('10');
Output would be table with one column indicating 10 weeks interval.
http://sqlfiddle.com/#!17/4b404/5/0
One take would be to create constant interval of 1 week and multiply it by integer.
I would prefer function to do it directly, but I am not aware of it.
SELECT interval '1 week' * i AS weeks_interval FROM integers;
Your solution is well accepted.
If you don't want to keep the "1" in the string you could write this instead
SELECT (i || 'week')::interval FROM intervals
demo: db<>fiddle

date and time concatenation in postgres

I wanted to get the only the hour of the time and concatenate it with the date.
here's my query
SELECT distinct TOTALIZER_METER_READINGS.date + to_char(TOTALIZER_METER_READINGS.time ,'HH')
FROM TOTALIZER_METER_READINGS
is there any other way to get the hour of the time without turning it into text?
+ is the operator to add numbers, dates or intervals.
The string concatenation operator in SQL is ||.
As you are storing date and time in two columns rather then using a single timestamp column, I would convert them to a single timestamp value, then apply to_char() on the "complete" timestamp:
Adding a time to a date returns a timestamp that can then be formatted as you want:
SELECT distinct to_char(TOTALIZER_METER_READINGS.date + TOTALIZER_METER_READINGS.time, 'yyyy-mm-dd HH')
FROM TOTALIZER_METER_READINGS
You can use EXTRACT (or the date_part function):
SELECT EXTRACT(hour FROM current_timestamp);
The result type is double precision.

Convert bigint data type to timestamp (and subsequently to date) in redshift

I need to convert the value stored in a bigint column to a date field. The first step of the conversion involves converting it to timestamp, and subsequently use the TRUNC method to convert this column to a date value.
However, my query is failing while converting the bigint value to timestamp.
The error that I'm getting is:-
Amazon Invalid operation: cannot cast type bigint to timestamp without time zone;
The query I'm trying for now is something like this:-
select ts::timestamp from events limit 1;
I was able to avoid the time zone error by using the method described in this thread: https://stackoverflow.com/a/36399361
My dates are based on epochs, and I was able to do the following:
SELECT
(TIMESTAMP 'epoch' + contract_start_date * INTERVAL '1 Second ')
FROM
table_name
SELECT TIMESTAMP 'epoch' + {column of bigint}/1000 * INTERVAL '1 second' as adate FROM tbl
If you are starting with a POSIX timestamp, and trying to get a timezone aware datetime value, you will need to supply a timezone - even if you later want to truncate the time part away. I'm not familiar with redshift, but perhaps there is a way to specify you mean UTC.

Postgresql. Dates interval issue

I'm trying to get difference in days, casting result to decimal:
SELECT
CAST( TO_DATE('2999-01-01','yyyy-mm-dd') - TO_DATE('2909-01-01','yyyy-mm-dd') AS DECIMAL )
;
Now if I add 1 month to the 2nd date:
SELECT
CAST( TO_DATE('2999-01-01','yyyy-mm-dd') - (TO_DATE('2909-01-01','yyyy-mm-dd') + INTERVAL '1 MONTH' * (1) ) AS DECIMAL )
;
I'm getting an error:
ERROR: cannot cast type interval to numeric
OK, I can cast to char to get result:
SELECT
CAST( TO_CHAR( TO_DATE('2909-02-10','yyyy-mm-dd') - (TO_DATE('2909-01-01','yyyy-mm-dd') + INTERVAL '1 MONTH' * (1) ), 'DD') AS DECIMAL )
;
But in this case the 1st query modified with TO_CHAR casting stop working:
SELECT
CAST( TO_CHAR(TO_DATE('2999-01-01','yyyy-mm-dd') - TO_DATE('2909-01-01','yyyy-mm-dd'), 'DD') AS DECIMAL )
;
I'm getting ERROR: multiple decimal points.
So, my question is, how can I get days using the same sql statement? For both sql queries.
Look at your first two examples again. If you remove the outer CAST ... AS DECIMAL you get
?column?
----------
32872
?column?
------------
32841 days
Clearly the difference is in the "days". The second is an interval value rather than a simple number. You only want the number (because you always just want days) so you need to extract that part. Then you can cast to whatever precision you like:
SELECT extract(days FROM '32841 days'::interval)::numeric(9,2);
date_part
-----------
32841.00
Edit responding to Alexandr's follow-up:
Your first example fails with a fairly specific error:
SELECT extract(days FROM (TO_DATE('2999-01-01','yyyy-mm-dd') - TO_DATE('2909-01-01','yyyy-mm-dd'))::interval)::numeric(9,2);
ERROR: cannot cast type integer to interval
LINE 1: ...yyyy-mm-dd') - TO_DATE('2909-01-01','yyyy-mm-dd'))::interval...
Here you've got an integer (which is what you originally wanted) and try to cast it to an interval (for reasons I don't understand). It's complaining it doesn't know what units you want. You want 32872 what in your interval - seconds, hours, weeks, centuries?
The second example is complaining because you are trying to extract the "day" part from a simple integer, and of course there's no extract() function in the system to do that.
I think you probably need to take a step back and just take the time to understand the values your various expressions return.
Subtracting one date from another gives the number of days separating them - as an integer. There is no other sensible measure, really.
Adding (or subtracting) an interval to a date gives you a timestamp (without time zone) since the interval may contain whole days, days and hours, seconds etc.
Subtracting a timestamp from a date will give you an interval since the result may contain days, hours, seconds etc.
If you have an interval and you just want the days part then you use extract() on it and you will get an integer number of days back.
You will need an integer (or floating-point) number of days if you want to cast to numeric, not an interval because casting an interval to an scalar number makes no sense without units.
So - either stick to dates and date arithmetic (easy), or realise you are using timestamps (flexible) but understand which it is.
To get an illustration of what's happening you can do something like this (in psql):
CREATE TEMP TABLE tt AS SELECT
('2909-01-02'::date - '2909-01-01'::date) AS a,
('2909-01-02'::date - '2909-01-02 00:00:00'::timestamp) AS b;
\x
SELECT * FROM tt;
\d tt
That will show you the values and types you are dealing with. Repeat for as many columns as you find useful.
HTH
If you're doing interval arithmetic with dates, you should generally be using timestamps instead, as mentioned in the docs.
# SELECT extract(days FROM TO_TIMESTAMP('2999-01-01','yyyy-mm-dd') - TO_TIMESTAMP('2909-01-01','yyyy-mm-dd'))
date_part
-----------
32872
# SELECT extract(days FROM TO_TIMESTAMP('2999-01-01','yyyy-mm-dd') - (TO_TIMESTAMP('2909-01-01','yyyy-mm-dd') + '1 month'::interval) );
date_part
-----------
32841
The result of adding an interval to a date is actually a timestamp, not another date (the interval might have contained time portions), so you have to cast the result of the addition back down to date first:
SELECT
CAST( TO_DATE('2999-01-01','yyyy-mm-dd')
- CAST( (TO_DATE('2909-01-01','yyyy-mm-dd') + INTERVAL '1 MONTH' * (1) ) AS DATE)
AS DECIMAL )

how to compare date range in a varchar coloumn

I have two varchar(30), startDate and endDate coloumn and it has dates values and also nulls in that coloumn. I want to compare the date range in sql server 2005/2008. someting like
WHERE e2.type=1
AND coloumn1 between convert(datetime,startDate,101) and convert(datetime,endDate,101)
When i try to execute it gives me an error
the conversion of varchar data type to a datetime data type resulted in an out-of-range value.
That error message indicates that the value stored in the varchar cannot be converted (by SQL) into a datetime. You will need to drill down in your data and locate the problem row(s), which can be a tricky thing to do. Start with something like:
SELECT StartDate, isdate(StartDate)
from MyTable
where StartDate is not null
and isdate(StartDate) = 0
...and the same for EndDate. You will have to play around with this, as string-to-date conversion is can get tricky fast. (Needless to say, you would be much better off storing datetime values as datetime values. If you can change your table structure, do so!)