5

我要做的是将 CSV 上传到表中,同时使用 JOIN 将第三个表中的信息附加到目标表中。

CSV import.csv(有 1M 行)如下所示:

firstname | lastname

目标表“名称”如下所示:

firstname | lastname | gender

表“gender”(有 700k 行)如下所示:

firstname | gender

所以,我理想的查询应该是这样的:

LOAD DATA LOCAL INFILE "import.csv"
INTO TABLE names n
LEFT JOIN gender g ON(g.firstname=n.firstname)

沿着这些思路,将导入与连接结合起来,因此名称中的最终结果包含来自性别和 CSV 的数据。

但是,我知道 LOAD DATA LOCAL INFILE 不能与 JOIN 结合使用,并且尝试对每一行使用 INSERT 和 JOIN 的 CPU 密集度过高。

有任何想法吗?

4

3 回答 3

12

您可以使用SET从句LOAD DATA INFILE来实现您的目标

LOAD DATA LOCAL INFILE '/path/to/your/file.csv'
INTO TABLE names
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' 
LINES TERMINATED BY '\n' -- or '\r\n' if file has been prepared in Windows
IGNORE 1 LINES -- use this if your first line contains column headers 
(@first, @last)
SET firstname = @first,
    lastname = @last,
    gender = 
    (
      SELECT gender 
        FROM gender
       WHERE firstname = @first
       LIMIT 1
    )

确保:

  • 您在表中的firstname列上有一个索引gender
  • names在加载数据之前,表上没有任何索引。完成加载后添加它们(索引)。
于 2013-09-01T01:58:00.757 回答
2

MySql LOAD DATA INFILE语法没有定义 JOIN。

  1. 创建表临时表...
  2. LOAD DATA INFILE "import.csv" INTO TABLEtemporary_table FIELDS TERMINATED BY '|' 由 '"' 包围的行以 '\n' 终止;
  3. INSERT INTO names(t.firstname, t.lastname, g.gender) SELECT FROM temporary_table t LEFT JOIN gender g ON(g.firstname=n.firstname);
于 2013-08-31T20:24:31.890 回答
1

根据我的经验,将数据加载到数据库中的最佳方法是首先将其放置在所有列都是字符的临时表中。然后,将数据库中的数据转换为最终输出。

将此应用于您的代码:

LOAD DATA LOCAL INFILE "import.csv"
INTO TABLE names_staging;

CREATE TABLE names as
    select n.firstname, n.lastname, g.gender
    from names_staging n LEFT JOIN
         gender g
         ON g.firstname = n.firstname;

这使得从数据加载中识别和修复问题成为可能。您还可以轻松地添加其他列,例如主键并将日期插入到最终表中。

于 2013-08-31T19:38:38.253 回答