简体   繁体   中英

SQL: Add UTC timestamp column to table from date and time

I have a table in Postgres that has a date column and time column. I would like to add a new column that has utc (or timestamp) values based on on the date and time columns.

I tried the following:

INSERT INTO mytable (utc) SELECT EXTRACT(EPOCH FROM (date || ' ' || time )::timestamp);

But I get the error:

ERROR: column "date" does not exist
SQL state: 42703
Hint: There is a column named "date" in table "mytable", but it cannot be referenced from this part of the query.

And there definitely are the columns date and time.

Does anyone know how to add values to UTC column based on date and time columns?
For example: 09/21/2012 12:56:00 should become something like 411730.830555

I'm trying to do something similar to this question (I think).

What you want to do

To add a new column you need an alter table statement:

alter table mytable add column utc float;

Then you need to update that column with the new data:

update mytable
  set utc = EXTRACT(EPOCH FROM (date || ' ' || time )::timestamp);

You now need a trigger that keeps the date/time and utc columns in sync.

What you should do

The above is not a good idea. The rule of thumb in a relational database:

Never store information that can be derived from the data that is already in the database.

So the clean solution is to not store date and time in two different columns and not add another column that contains exactly the same information in a different representation.

You should have a single column with the type timestamp , then create a view that returns that timestamp with the different formats you want:

-- add the new timestamp column
alter table mytable add column ts_column timestamp;

-- copy the data 
update mytable
  set ts_column = (date || ' ' || time )::timestamp;

-- get rid of the old columns
alter table mytable 
     drop column date, 
     drop column time;

-- now create a view that display the information in different ways              
create view formatted_mytable
as
select id, 
       ts_column, 
       to_char(ts_column, 'yyyy-mm-dd') as date_only, 
       to_char(ts_column, 'hh24:mi:ss') as time_only, 
       extract(epoch from ts_column) as epoch
from my_table;

That way you don't need to duplicate the information stored in the table just because you need a different display format.

The formatting from the other answer was actually different than what I wanted, upon further investigating.

I mentioned the formatting desired was ddddd.tttttt where d is a numerical version of a date (specifically, the number of days since 1900-01-00), and t is a fraction of 24 hours. This is the format Excel uses to store date-time values, called "serial date-time." For more information see Dates and Times in Excel.

I thought this was similar to postgresql's timestamp format, but it turned out to not work for my purposes.

This is what worked:

UPDATE mytable SET utc = DATE_PART('day', '2012-09-21'::timestamp - '1899-12-30'::timestamp) + (EXTRACT( HOURS FROM time::time)/24) + (EXTRACT( MINUTES FROM time::time)/1440) + (EXTRACT( SECONDS FROM time::time)/86400);

Just wanted to update the answers for accuracy and in case anyone else stumbles into this problem. It appears there's little information on how to do this on the internet. I appreciate the answer from @a_horse_with_no_name; that did help me in some ways.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM