Select datetime in postgres - postgresql

Must be missing something very simple here. Maybe someone can answer this. You want to select from a datetimestamp to now. Why would the where clause return nothing with this?
select * from xyz where ('2020-01-29 04:18:00-06'::timestamptz > CURRENT_TIMESTAMP);
when
select CURRENT_TIMESTAMP;
current_timestamp
-------------------------------
2020-01-29 04:47:06.011133-06
(1 row)
Time: 0.258 ms
Should not be that hard in PostgreSQL to get every row from a certain time to current time to see what has been added or new / changed.
I found the answer to this problem with the help here. First try I did not post was using between. It should have been used like this. Need to remove timestamp from the where clause and use BETWEEN!
TABLENAME.COL-NAME-FOR-TIMESTAMP BETWEEN '2020-01-29 04:18:00-06' AND CURRENT_TIMESTAMP
TABLENAME.COL-NAME-FOR-TIMESTAMP should be your column in the table you are referencing for datetime.
Hope this helps someone!

The explanation is that your current timestamp, in the time zone of your Postgres server, is past 4:18am on January 29, 2020. Try setting your time zone to something which should make your current query pass, e.g.
SET timezone = 'America/Los_Angeles'; -- 2:58 AM as of the time this answer was posted
SELECT * FROM xyz WHERE '2020-01-29 04:18:00-06'::timestamptz > CURRENT_TIMESTAMP;
I suspect that the doubt here is that you are expecting your Postgres server to be set to a certain time zone, so you should look into this.

Related

postgresql - why is now() is not right after saving?

so it's like this, I have a procedure like this :
CREATE OR REPLACE PROCEDURE public.savetrbankd(
_transcode text,
_id integer,
_expensecode text,
_debetamt numeric,
_creditamt numeric)
LANGUAGE 'plpgsql'
AS $BODY$
Declare
BEGIN
If _id=0 Then
INSERT INTO trbankd(transcode,expensecode,ket,debetamt,creditamt)
VALUES(_transcode,_expensecode,_ket,_debetamt,_creditamt);
Else
UPDATE trbankd SET
expensecode=_expensecode,
debetamt=_debetamt,
creditamt=_creditamt,
LastUpdatedDate=now()
WHERE transcode=_transcode and id=_id;
END IF;
END;
$BODY$;
lets pay attention to field "lastupdateddate" here. The type is timestamp without time zone, and default value of now().
so after inserting/updating the records with this procedure, I tried to query the data again.
so I got :
2021-07-23 23:48:42.805869
but when I insert/update the records, it should be 24 jul 2021 about 1 pm.
so we got the different in timezone about 13-14 hours ?
sure, then when I tried to show timezone, it said it was us/pacific.
then I set the timezone to asia/bangkok (which is my real timezone), with code like : set timezone='Asia/Bangkok'.
the data wasnt changed. it still said lastupdateddate on 23 jul 2021.
Ok, maybe the previous entered data wont change as I used timestamp without time zone type. So I tried to update the data again with the stored procedure, and it still shown 2021-07-24 00:29:23.384443 <= note, that I wasted some time trying to figure out the timezone, so when I updated it the 2nd time here, it's about 1 hour already, and my real time is about 2 pm.
so it's still the same different of about 13-14 hours.
how could I make sure that the data inserted and queried to be the same with the server (which happened to be my computer here).
as an added note, my setting control panel region is us (english), my location has been set to indonesia (gmt +7), and my current time in my computer is right (like I told above it was 1-2pm).
thx in advance
What you have discovered is that storing timestamp data in a timestamp without time zone field is generally not a good idea, especially when working across time zones. For detailed information on how timestamp without time zone(timestamp) and timestamp with time zone(timestamptz) work with time stamps see here:
https://www.postgresql.org/docs/current/datatype-datetime.html
8.5.1.3. Time Stamps
To illustrate what you are seeing:
select '2021-07-23 23:48:42.805869'::timestamp AT time zone 'US/Pacific';
timezone
-------------------------------
2021-07-23 23:48:42.805869-07
select '2021-07-23 23:48:42.805869'::timestamp AT time zone 'US/Pacific' AT time zone 'Asia/Bangkok';
timezone
----------------------------
2021-07-24 13:48:42.805869
---Current time here(I'm in 'US/Pacific')
test(5432)=# show timezone;
TimeZone
------------
US/Pacific
(1 row)
test(5432)=# select now()::timestamp;
now
----------------------------
2021-07-24 08:57:07.780014
test(5432)=# set timezone = 'Asia/Bangkok';
SET
test(5432)=# select now()::timestamp;
now
----------------------------
2021-07-24 22:56:14.659657
The now() is picking up the time zone set in the server(or reset via the client)and using that to create the timestamp. Since it is being stored to timestamp there is no timezone offset. Your choices for dealing with this are:
Leave it as it is, timestamp without time zone field and timezone='US/Pacific'. Do the translation to local time zone as needed.
Convert field to timestamp with time zone. Before you do this though you will need to be certain you know what the current values actually represent.

Subtract HOURS from CURRENT_TIMESTAMP (DB2)

I need to substract 4 hours from CURRENT_TIMESTAMP in DB2, my query in SQL DEVELOPER is correct because I can see the registers I need to see, but when I do the query in Eclipse have some problem and I don't know which is. This is the query I need to do:
"SELECT yerror, COUNT(yerror) AS CantidadErrores FROM kexg.VD03154 WHERE tumod BETWEEN (CURRENT_TIMESTAMP - 4 HOUR) AND CURRENT_TIMESTAMP GROUP BY yerror;";
This query returns me an error but if I put 24 HOUR is correct. Also is correct if I put 5 DAYS for example.
I have try to subtract 04 HOUR, and it's wrong also.
Thanks in advance
The following works beautifully for me on DB2 for z/OS:
select current timestamp as rightnow,
current timestamp - 4 hours
from sysibm.sysdummy1
;
RIGHTNOW COL1
-------------------------- --------------------------
2020-02-27-08.16.55.142456 2020-02-27-04.16.55.142456

postgresql table data movement

In PostgreSQL i want to create script which can delete old data of before 1 month from A table(which contain many rows) and insert this data into one new alias table. and i want to execute this script every month.
for that i have created script as
insert into B select * from A where date >(now-'30 day'::interval);
delete from A where date <(now()-'30 days.
but in some month there is 30 days and in some 31 days .so how can i set this in cron tab to delete exact data and move in alias table.
While Laurenz answer makes much sense and seems to be a good guess of what OP really wants (cron monthly probably means he wants to flush not "older than one month", but of "previous month" so date_trunc to month is a case)
Yet answering it the other way (as I understand the original post):
begin;
insert into B select * from A where date >(now()-'1 month'::interval);
delete from A where date <(now()-'1 month'::interval);
end;
will delete not all data for previous month, but same timestamp one month ago, eg:
t=# select now()-'1 month'::interval;
?column?
-------------------------------
2017-05-12 07:31:31.785402+00
(1 row)
And with this logic you might want to schedule this data purge daily, not monthly - to keep last month data in active table, not "up to two" untill cron fires...
run it on the first of every month and write it like this:
... WHERE date >= date_trunc('month', current_timestamp) - INTERVAL '1 month'
AND date < date_trunc('month', current_timestamp)
If your table contains a lot of data, you might want to look into partitioning.

postgresql ignore milliseconds from timestamp when doing a select statement

I have TableA and it has a field of
time_captured | timestamp without time zone | default now()
It is being used to record when data was inserted into the table. However, I am trying to do a select and ignore milliseconds.
So instead of having
2015-07-11 18:06:33.690498
2015-07-12 13:36:21.274509
2015-07-12 13:36:24.222577
2015-07-12 13:36:26.515593
I would like to have
2015-07-11 18:06:33
2015-07-12 13:36:21
2015-07-12 13:36:24
2015-07-12 13:36:26
Having the microseconds in the table is needed but what I do not need is for the output to show the microseconds.
How can I do this ?
The closest I have come is by using the following but I am not able to figure out how to pull the full date with the time as shown above.
SELECT EXTRACT(YEAR FROM time_captured AT TIME ZONE 'UTC') FROM server_perf; date_part
Thank you :)
You can use the date_trunc function to achieve this:
select date_trunc('second', time_captured) from server_perf;
see http://www.postgresql.org/docs/9.1/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC for more on this.

Calculate the sum of time column in PostgreSql

Can anyone suggest me, the easiest way to find summation of time field in POSTGRESQL. i just find a solution for MYSQL but i need the POSTGRESQL version.
MYSQL: https://stackoverflow.com/questions/3054943/calculate-sum-time-with-mysql
SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(timespent))) FROM myTable;
Demo Data
id time
1 1:23:23
2 4:00:23
3 9:23:23
Desired Output
14:47:09
What you want, is not possible. But you probably misunderstood the time type: it represents a precise time-point in a day. It doesn't make much sense, to add two (or more) times. f.ex. '14:00' + '14:00' = '28:00' (but there are no 28th hour in a day).
What you probably want, is interval (which represents time intervals; hours, minutes, or even years). sum() supports interval arguments.
If you use intervals, it's just that simple:
SELECT sum(interval_col) FROM my_table;
Although, if you stick to the time type (but you have no reason to do that), you can cast it to interval to calculate with it:
SELECT sum(time_col::interval) FROM my_table;
But again, the result will be interval, because time values cannot exceed the 24th hour in a day.
Note: PostgreSQL will even do the cast for you, so sum(time_col) should work too, but the result is interval in this case too.
I tried this solution on sql fieddle:
link
Table creation:
CREATE TABLE time_table (
id integer, time time
);
Insert data:
INSERT INTO time_table (id,time) VALUES
(1,'1:23:23'),
(2,'4:00:23'),
(3,'9:23:23')
query the data:
SELECT
sum(s.time)
FROM
time_table s;
If you need to calculate sum of some field, according another field, you can do this:
select
keyfield,
sum(time_col::interval) totaltime
FROM myTable
GROUP by keyfield
Output example:
keyfield; totaltime
"Gabriel"; "10:00:00"
"John"; "36:00:00"
"Joseph"; "180:00:00"
Data type of totaltime is interval.