【问题标题】:Loading Denormalized Data Into A Database将非规范化数据加载到数据库中
【发布时间】:2013-10-26 02:09:22
【问题描述】:

我有一个包含两个表的数据库(postgres):

CREATE TABLE invoices (
    id bigint,
    some_data varchar
)

CREATE TABLE charges (
    id bigint,
    invoice_id bigint,
    some_data varchar
)

我正在尝试将具有以下格式的 csv 文件加载到此数据库中:

invoice_id, invoice_data, charge_id, charge_data

例如,我的 csv 文件中可能包含以下几行:

1, $10.00, 1, $2.00
1, $10.00, 2, $5.00
1, $10.00, 3, $3.00
2, $2.00,  4, $1.00
2, $2.00,  5, $1.00
3, $11.00, 6, $11.00

此数据应对应数据库中的以下记录:

SELECT * FROM invoices;
  id | some_data
-----+-------------
  1  | $10.00
  2  | $2.00
  3  | $11.00

SELECT * FROM charges;
  id | invoice_id | some_data
-----+------------+-------------
  1  | 1          | $2.00
  2  | 1          | $5.00
  3  | 1          | $3.00
  4  | 2          | $1.00
  5  | 2          | $1.00
  6  | 3          | $11.00

是否有加载此类数据的“最佳做法”?目前,我正在将此文件加载到中间表中并使用 php 脚本处理它(坏)。这是相当低效的。有没有更好的办法?我应该将其加载到中间表中,然后使用存储过程来拆分信息吗?还是我应该直接处理我的 .csv 文件并将这些信息拆分为某种脚本?

【问题讨论】:

  • 首先加载到临时表(使用 COPY),然后使用普通 SQL 将数据分发到两个目标表是加载和按摩数据的常用方法。
  • 我应该为此创建一个存储过程吗?或者只是将 sql 与文件加载脚本一起保存在某个地方?
  • 一个 db 函数(在 Postgres 中它们是函数,而不是存储过程)是一种简单的方法来封装将数据从一个表移动到另一个表的逻辑,所以是的,它工作得很好。如果列和表定期更改,在加载脚本中保留纯 SQL 可能更有意义,但如果它是相当静态的,我会倾向于走函数路线。

标签: php sql postgresql csv


【解决方案1】:

您可以使用 COPY 命令将数据先加载到结构与 CSV 匹配的中间表中(例如:COPY intermediary_table FROM '/path/to/csv/charges.csv'DELIMITER','CSV;),然后将数据选择到每个表中。第一个查询是 SELECT DISTINCT invoice_id, invoice_data INTO invoices FROM intermediary_table,第二个查询是 SELECT DISTINCT charge_id, invoice_id, charge_data INTO charge FROM intermediary_table。

顺便说一句,您很可能不需要使用 bigint(除非您期望有数十亿行)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-09
    • 2011-03-27
    • 1970-01-01
    • 1970-01-01
    • 2016-07-23
    • 2013-01-18
    • 2012-11-18
    • 2019-01-17
    相关资源
    最近更新 更多