0

我有一个数据集(.tsv 格式),其中一列是date ofbirth。但是,数据很旧,并且并非所有日期都是YYYY-MM-DD格式。一些条目只有他们的出生年份(缺少出生月份和日期)并且采用格式YYYY-##-##(字面上##的 's 已经插入数据中,只要知道年份)。我希望将此数据集加载到我的postgres数据库中,出生日期列的数据类型为 asdate和 not string,以便我可以对日期进行比较。
一个小样本如下所示。(不相关的数据列未显示)

1924-##-##
1965-09-04
1944-11-05
1951-##-##
-388-##-##
1893-01-26
1037-##-##

直接批量加载数据集显然会出错

ERROR:  invalid input syntax for type date: "1924-##-##"
LINE 1: insert into d values ('1924-##-##');
                              ^

数据集非常大,大约有 6 千万个条目。目前我正在考虑运行一个脚本来替换这些##01然后将修改后的数据插入到数据库中。但我不喜欢这个主意——

  1. 这很耗时。
  2. 这会占用磁盘空间(因为我想保留原始的“未篡改”数据)
  3. 此外,并非我的所有数据在我的数据库中都是真实的。

有什么方法可以让 postgres 以某种方式直接获取日期,只需忽略“##”(并保留缺少月份和日期的年份)?
或者有没有更好的办法解决这个问题?

4

3 回答 3

1

您可以在表中创建两列,一列用于最初输入的值(varchar 类型),另一列用于计算(日期类型)。

CREATE TABLE your_table
(
 id INT,
 -- OTHER DETAILS
 dob_entered    VARCHAR,
 dob_parsed DATE
);

然后,您可以在 Insert 触发器上使用自动填充 varchar 中的日期字段,并使用更新触发器来处理任何更改。

CREATE OR REPLACE FUNCTION evaluate_dob_date() RETURNS TRIGGER AS
$$
BEGIN
    NEW.dob_parsed = CAST(REPLACE(NEW.dob_entered,'##','01') AS DATE);
    RETURN new;
END;
$$
LANGUAGE plpgsql;

CREATE TRIGGER parse_dob 
BEFORE INSERT OR UPDATE ON your_table
FOR EACH ROW
EXECUTE PROCEDURE evaluate_dob_date();

这将意味着您将原始输入的数据都存储为未触及以进行验证,同时在数据库中仍有一个日期字段适合排序和比较等。此外,通过扩展该evaluate_dob_date()功能,您可以在找到它们时匹配不同的情况,同时仍然能够拒绝真正无效的记录。

Postgresql 触发器

于 2012-01-29T18:41:20.657 回答
0

如果您需要保留#字符,我看到的唯一机会是将其导入varchar列中。

如果您绝对需要将信息作为日期,您可能会得到一个执行转换的视图,并且只选择列中没有#的那些行。

就像是

SELECT to_date(dob,'YYYY-MM-DD') as dob_date
FROM your_table
WHERE substr(dob,6,2) <> '##';

如果您定期执行此操作,您可能需要考虑对该表达式的索引以加快选择速度:

CREATE INDEX dob_check ON your_table( substr(dob,6,2) );

请注意,您的选择中的表达式必须与索引中的表达式完全匹配,以便查询计划器可以使用。

如果您想在检索期间将数据“转换”为有效日期,您可以执行以下操作:

SELECT case 
         case when substr(dob,6,2) = '##' then to_date(substr(dob,1,5)||'01-01', 'YYYY-MM-DD')
         else to_date(dob,'YYYY-MM-DD')
       end as dob_date
FROM your_table;
于 2012-01-28T09:40:21.133 回答
0

你在这里有两个选择

  1. 从数据库中获取数据后,替换服务器端脚本中所有出现的#,然后比较日期。(您也可以在表本身中动态替换数据,而无需在查询中使用 if 条件修改现有数据)
  2. 忽略带有# 的日期。这样您就可以只比较有效日期。
于 2012-01-28T06:51:56.557 回答