No value is added into the column - postgresql

I am trying to find the difference between the Unix seconds and adding into the existing null column but the results are not added into the column. As I am new I can't figure it out.
INSERT INTO "Operation"(minutes)
select (departure_unix_seconds - arrival_unix_seconds)/60 As Difference
from public."Operation";

assuming you have a column in your table called "minutes" , and you want to update that column , here is the syntax:
update public."Operation"
set minutes = (departure_unix_seconds - arrival_unix_seconds)/60
however usually when a column value depends on other column(s) ,It's better to be implemented as "generated column":
alter table Operation
add column minutes generated always as (departure_unix_seconds - arrival_unix_seconds)/60 stored;

Related

How to convert varchar to timestamp in postgreSQL?

I have data as following, But the column type is Varchar:
2019-09-28T23:59:59.52Z
I assume 52 here is milli seconds, If so..
I would like to convert it as following and change the column type to timestamp:
2019-09-28 23:59:59.52
Can someone let me know how I can convert in postgreSQL?
EDIT:
I can see data in table as (since the column type is varchar):
2019-09-28T23:59:59.52Z
Instead, I want data in the table to be shown as:
2019-09-28 23:59:59 ( and may be .52, if possible)
I need to change the column type to timestamp as well, I guess, Please help with that too.
Answer:
Tim has provided a solution, You can follow that.
But, In my case, It is prod env, So, I have just changed the type using:
ALTER TABLE my_table ALTER COLUMN my_column TYPE TIMESTAMP USING my_column::timestamp without time zone;
Thanks
Your timestamp string literal is already in a format which can be directly cast in Postgres:
SELECT '2019-09-28T23:59:59.52Z'::timestamp; -- 2019-09-28 23:59:59.52
As a test, let's add one day to make sure it's working:
SELECT '2019-09-28T23:59:59.52Z'::timestamp + interval '1 day';
-- 2019-09-29 23:59:59.52
If you want to actually add a new timestamp column using string data from another column, then try:
ALTER TABLE yourTable ADD COLUMN new_ts TIMESTAMP;
UPDATE yourTable SET new_ts = old_ts::timestamp;
ALTER TABLE yourTable DROP COLUMN old_ts;
ALTER TABLE yourTable RENAME COLUMN new_ts TO old_ts; -- optional
The last ALTER statement is optional if you want the new bona fide timestamp column to bear the same name as the old text timestamp column.

Postgres - create a column (alter table) as a calculation of other two columns

I have a table in Posgres that contains task start and task end dates. It's possible to generate a column in this tale as rate between (current day -start day) /(start day-end day) the column is the % of time elapse. I try in this way but does not work.
ALTER TABLE public.gantt_task
ADD COLUMN
percentage_progress
GENERATED ALWAYS AS (
(DATEDIFF("day",
CURRENT_DATE,public.gantt_Tasks.start_date)) / DATEDIFF("day", public.gantt_Tasks.end_date ,public.gantt_Tasks.start_date))
STORED
The manual says postgres only supports materialized (ie, stored) generated columns, which means the value is generated when the row is inserted or updated, which means it will use the insert/update date, not the CURRENT_DATE you want.
So, you need to create a view instead. This allows evaluating CURRENT_DATE at the date of the SELECT, not the INSERT/UPDATE, to generate columns.
CREATE VIEW foo AS SELECT *,
(CURRENT_DATE - public.gantt_Tasks.start_date)
/ (public.gantt_Tasks.end_date-public.gantt_Tasks.start_date)
AS percentage_progress
FROM public.gantt_task
Note DATEDIFF is mysql syntax not postgres, and division by zero is not allowed, so if start_date and end_date can be identical then you'll have to modify the expression conditions depending on what you want. Also your expression will go over 100% when CURRENT_DATE is later than end_date. Perhaps something like:
least( 1.0, (CURRENT_DATE-start_date)/greatest( 1, end_date-start_date)::FLOAT )
I won't write proper SQL code. But you might/should split it into two or three tasks:
Add new column that allows null (that should be default)
Update table
Add constrains (if required)

How can I sum/subtract time values from same row

I want to sum and subtract two or more timestamp columns.
I'm using PostgreSQL and I have a structure as you can see:
I can't round the minutes or seconds, so I'm trying to extract the EPOCH and doing the operation after, but I always get an error because the first EXTRACT recognizes the column, but when I put the second EXTRACT in the same SQL command I get an error message saying that the second column does not exist.
I'll give you an example:
SELECT
EXAMPLE.PERSON_ID,
COALESCE(EXTRACT(EPOCH from EXAMPLE.LEFT_AT),0) +
COALESCE(EXTRACT(EPOCH from EXAMPLE.ARRIVED_AT),0) AS CREDIT
FROM
EXAMPLE
WHERE
EXAMPLE.PERSON_ID = 1;
In this example I would get an error like:
Column ARRIVED_AT does not exist
Why is this happening?
Could I sum/subtract time values from same row?
Is ARRIVED_AT a calculated value instead of a column? What did you run to get the query results image you posted showing those columns?
The following script does what you expect, so there's something about the structure of the table you're querying that isn't what you expect.
CREATE SCHEMA so46801016;
SET search_path=so46801016;
CREATE TABLE trips (
person_id serial primary key,
arrived_at time,
left_at time
);
INSERT INTO trips (arrived_at, left_at) VALUES
('14:30'::time, '19:30'::time)
, ('11:27'::time, '20:00'::time)
;
SELECT
t.person_id,
COALESCE(EXTRACT(EPOCH from t.left_at),0) +
COALESCE(EXTRACT(EPOCH from t.arrived_at),0) AS credit
FROM
trips t;
DROP SCHEMA so46801016 CASCADE;

Capture RowVersion on Insert

My tables have a RowVersion column called LastChanged.
ID | LastChanged | Foo |
I am developing some sync related functionality. I will be selecting all records from the table between a min and max RowVersion. The initial sync won't have a Min Row Version so I will be including all rows upto MIN_ACTIVE_ROWVERSION().
Subsequent syncs will have a min RowVersion - typically it will be the MIN_ACTIVE_ROWVERSION() from the previous sync.
Selecting rows that are between the Min and Max RowVersion like this is easy. However I would also like to determine, which of those rows, are Inserts and which rows are Updates. The easiest way for me to do this, is to add another column:
ID | LastChanged (RowVersion) | CreationRowVersion (Binary(8)) | Foo |
For CreationRowVersion - The idea is to capture the RowVersion value on insert. That value will then never change for the row. So I would like to default CreationRowVersion to the same value as RowVersion when the row is initially Inserted.
With this in place, I should then be able to determine which rows have been created, and which rows have been updated since the last sync (i.e between min and max RowVersions) - because for created rows, I can look at rows that have a CreationRowVersion that fall within the min and max row version range. For Updated Rows, I can look at rows that have a LastChanged that fall within min and max row version range - but I can also exclude rows from being detected as "Updates" if their CreationRowVersion also falls between min and max RowVersions as then I know they are actually already included as Inserts.
So now that the background is out of the way, it brings me to the crux of my question. What is the most efficient way to default CreationRowVersion to the RowVersion on Insert? Can this be done with a default constrain on the column, or does it have to be done via a trigger? I'd like this column to be a Binary(8) as this matches the datatype of RowVersion.
Thanks
Try using the MIN_ACTIVE_ROWVERSION() function as the default value for your CreationRowVersion BINARY(8) column.
CREATE TABLE dbo.RowVerTest (
ID INT IDENTITY,
LastChanged ROWVERSION,
CreationRowVersion BINARY(8)
CONSTRAINT DF_RowVerTest_CreationRowVersion DEFAULT(MIN_ACTIVE_ROWVERSION()),
Foo VARCHAR(256)
)
GO
INSERT INTO dbo.RowVerTest (Foo) VALUES ('Hello');
GO
--[LastChanged] and [CreationRowVersion] should be equal.
SELECT * FROM dbo.RowVerTest;
GO
UPDATE dbo.RowVerTest SET Foo = 'World' WHERE ID = 1;
GO
--[LastChanged] should be incremented, while [CreationRowVersion]
--should retain its original value from the insert.
SELECT * FROM dbo.RowVerTest;
GO
CAUTION: in my testing, the above only works when rows are inserted one at a time. The code for the scenario below does not appear to work for your use case:
--Insert multiple records with a single INSERT statement.
INSERT INTO dbo.RowVerTest (Foo)
SELECT TOP(5) name FROM sys.objects;
--All the new rows have the same value for [CreationRowVersion] :{
SELECT * FROM dbo.RowVerTest;
There is an existing question about referencing columns in a default statement. You can't do it, but there are other suggestions to look at, including an AFTER INSERT trigger.
You may want to take a look at this question on RowVersion and Performance.

update Query in db2

My table looks like below,
Table Name: Number_List
Columns Name: Num_ID INTEGER
First_Number VARCHAR(16)
Last_Number VARCHAR(16)
In that, Num_ID is PK. and the rest of the columns First_Number and Last_Number always have a 8 digit number.
my requirement is to update that column to 6 Digit entry..
Consider the Entries in the two columns are 32659814 (First_Number) and 32659819 (Last_Number). Now I need to write a update query to change the entries in the table to 326598 (First_Number) and 326598 (Last_Number).
and this table has 15K entries and i need to update the whole in single query in single execution.
Please help me to resolve this.
TIA.
All you need is SUBSTR:
UPDATE SESSION.NUMBER_LIST
SET FIRST_NUMBER = SUBSTR(FIRST_NUMBER, 1,6)
,LAST_NUMBER = SUBSTR(LAST_NUMBER, 1,6)