我有一个数据集(格式为.tsv),其中一列是出生日期。但是,数据是旧的,并非所有日期都是YYYY-MM-DD
格式。有些条目只有他们的出生年份(出生月份和出生日期),并且格式YYYY-##-##
(字面上##
已经插入数据中,只有年份已知)。我希望将此数据集加载到我的 postgres 数据库中,并使用出生日期列,数据类型为date
而不是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
,然后将修改后的数据插入数据库。但我不喜欢这个想法 -
有什么方法可以让postgres以某种方式只是按照日期,只是忽略`##'(只保留缺少月份和日期的年份)? 或者可以有更好的解决方案解决这个问题吗?
答案 0 :(得分: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()
功能,您可以匹配不同的你找到它们的情况,同时仍然可以拒绝真正无效的记录。
答案 1 :(得分:0)
这里有两个选择
答案 2 :(得分: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中的表达式必须与完全索引中的表达式匹配才能被查询计算器使用。
如果您想在检索期间将数据“转换”为有效日期,您可以执行以下操作:
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;