PostgreSQL,R和没有时区的时间戳

PostgreSQL, R and timestamps with no time zone

我正在读一个大csv(> 1GB对我来说很大!)。它包含一个时间戳字段。
我从优秀的data.table包中读取了fread(100行开头)。

1
ddfr <- fread(INPUT="~/file1.csv",nrows=100, header=T)

问题1(已解决):时间戳字段(称为"ts"和"更新"),例如"02/12/2014 04:40:00 AM"转换为字符串。我使用lubridate包mdh_hms将字段转换回时间戳。灿烂。

1
ddfr$ts <- DATA.frame( mdy_hms(ddfr$ts))

问题2(未解决):根据POSIXlt创建时区的时间戳。

如何在R中创建没有时区的时间戳?可能吗??

现在我使用另一个(新的)优秀软件包PivotalR,使用as.db.data.frame将数据帧写入PostGreSQL 9.3。它充当魅力。

1
x <- AS.db.data.frame(ddfr, TABLE.name="tbl1", conn.id = 1)

问题3(未解决):由于原始数据帧时间戳字段具有时区,因此将创建一个表,其中包含"带时区的时间戳"字段。最终,数据需要存储在一个表中,其中字段配置为"无时区的时间戳"。

但是在Postgres的表格中,数据存储为"2014-02-12 04:40:00.0",其中.0末尾是UTC偏移量。我想我需要"2014-02-12 04:40:00"。

我试过了

1
ALTER TABLE tbl ALTER COLUMN ts TYPE TIMESTAMP WITHOUT TIME zone;

然后我复制了。当Postgres接受ALTER COLUMN命令时,当我尝试复制(使用INSERT INTO tbls SELECT ...)时,我收到一个错误:

1
2
  "column"ts" is of type timestamp without time zone but expression is of type text
  Hint: You will need to rewrite or cast the expression."

很明显,最后的.0不受欢迎(但为什么然后Postgres接受ALTER COLUMN?boh!)。

我试图在INSERT INTO查询中使用CAST执行错误建议:

1
INSERT INTO tbl2 SELECT CAST(ts AS TIMESTAMP WITHOUT TIME zone) FROM tbl1

但是我得到了同样的错误(包括建议使用CAST aargh!)

由PivotalR直接创建的表(基于数据框)具有以下CREATE脚本:

1
2
3
4
5
6
7
8
9
10
11
CREATE TABLE tbl2
(
  businessid INTEGER,
  caseno text,
  ts TIMESTAMP WITH TIME zone
 )
WITH (
  OIDS=FALSE
);
ALTER TABLE tbl1
  OWNER TO mydb;

我插入的表有这个CREATE脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
CREATE TABLE tbl1
(
  id INTEGER NOT NULL DEFAULT NEXTVAL('bus_seq'::regclass),
  businessid CHARACTER VARYING,
  caseno CHARACTER VARYING,
  ts TIMESTAMP WITHOUT TIME zone,
  updated TIMESTAMP WITHOUT TIME zone,
  CONSTRAINT busid_pkey PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE tbl1
  OWNER TO postgres;

我为复杂的解释道歉,但可能在链中的任何一步找到解决方案,所以我倾向于将所有步骤放在一个问题中。我相信必须有一个更简单的方法......


我认为你对在表之间复制数据感到困惑。

没有列列表的INSERT INTO ... SELECT期望源和目标中的列相同。它没有按名称神奇地匹配列,它只是从左到右将SELECT中的列分配到INSERT,直到它用完列,此时假定任何剩余的cols为null。所以你的查询:

1
INSERT INTO tbl2 SELECT ts FROM tbl1;

不这样做:

1
INSERT INTO tbl2(ts)  SELECT ts FROM tbl1;

它实际上是选择tbl2的第一列,即businessid,所以它真的试图这样做:

1
INSERT INTO tbl2(businessid)  SELECT ts FROM tbl1;

这显然是胡说八道,没有任何演员会解决这个问题。

(原始问题中的错误与您的表和查询不匹配,因此详细信息可能会有所不同,因为您明显错误地修改/混淆了表格或发布了比错误更新的表格版本。遗迹。)

假设您的表定义不会改变并且列顺序无论如何都不会改变通常是一个非常糟糕的主意。所以总是要明确列。在这种情况下,我认为你的意图实际上可能是:

1
2
3
INSERT INTO tbl2(businessid, caseno, ts)
SELECT CAST(businessid AS INTEGER), caseno, ts
FROM tbl1;

注意强制转换,因为businessid的类型在两个表之间是不同的。