【问题标题】:Using key in csv to retrieve corresponding multiple keys and their values with dbi使用 csv 中的键通过 dbi 检索对应的多个键及其值
【发布时间】:2014-01-26 19:24:05
【问题描述】:

抱歉标题,不知道更好的描述方式。我现在有点卡住了,需要一些帮助。

我正在尝试使用 DBI 从数据库中检索值。我有一个 CSV 文件,其中包含键和表中的多个对应键及其值。

CSV 看起来像这样,相当简单:

ID;Etc;Etc
10003999;Data;More Data;
10003800;Data;More Data;
10019764;Data;More Data;
10054483;Data;More Data;
10054540;Data;More Data;
10063434;Data;More Data;
10067815;Data;More Data;
10067819;Data;More Data;
10073005;Data;More Data;

数据库中的数据如下所示:

ID          Value
10003999    176
10003999    225
10003999    161
10003999    137
10003800    38
10003800    225
10003800    141
10003800    176
10003800    181
10003800    176
10003800    175
10003800    137
10019764    137
10073005    41

如您所见,csv 文件中的一个 ID 可以匹配数据库表中的多个 ID。 我要的是这个:

ID;Etc;Etc;;;
10003999;Data;More Data;176;225;161;137
10003800;Data;More Data;175;176;38;176;141;225;137;181
10019764;Data;More Data;137
10054483;Data;More Data;
10054540;Data;More Data;
10063434;Data;More Data;
10067815;Data;More Data;
10067819;Data;More Data;
10073005;Data;More Data;41

因为我不知道 ID 有多少对应的值,所以我将它们推送到数组中。它可以工作,但它只将一个值推送到数组(找到匹配项的位置),而不是 8(例如 id:10003859)。我该如何继续?我猜第二个循环?因为这超出了我的范围。这是我的剧本,也是我到目前为止所拥有的。它不是最好的代码,因为这是我必须使用的......我无法调整它或使用模块(dbi 除外)。老实说,我不擅长 Perl。

# Opening and connecting stuff here

my $sql_query = "SELECT id,value FROM `data`.`table`";
my $hash = $dbh->selectall_hashref($sql_query,'id');

my $i = 0;
my @infile=<INFILE>;

foreach (@infile) {
    my @elements = split(";",$infile[$i]);
    chomp(@elements);
    if (exists $hash->{$elements[$kolom_key]}) {
        my $value = $hash->{$elements[$kolom_key]}->{value};    
        push (@elements, $value);
        undef $value;
    };
    $elements[-1] = $elements[-1] . "\n";
    @elements = join(";",@elements);
    print OUTFILE "@elements"; 
    $i = $i+1;
}

$dbh->disconnect;
close(INFILE);
close(OUTFILE);

【问题讨论】:

  • 你没有给$kolom_key赋值
  • 没错,它在脚本中不可见.. 我使用 STDIN 为 $kolom_key 分配一个值(它在“打开和连接的东西”下)
  • 也许您应该查看文档,看看selectall_hashref 做了什么。然后使用Data::Dumperprint Dumper $hash 看看你实际拥有什么样的数据结构。如果可以避免的话,几乎总是首选不要一次获取所有数据,或者一次将整个文件读入数组。在这种情况下就是这样,并且可以使这变得相当简单。
  • csv 文件中的 ID 是否与数据库中的所有 ID 完全匹配? IE。您能否遍历其中任何一个并确保所有 ID 都已计算在内?
  • 我读过数据转储器,它看起来像一个有用的模块,所以我想使用它。非常适合告诉我发生了什么。但是现在我很高兴如果我能做到这一点。数据库中的 ID 完全相同。这应该是可能的,但我不知道该怎么做

标签: mysql perl csv dbi


【解决方案1】:

这对行重复了一些工作:

foreach (@infile) {
    my @elements = split(";",$infile[$i]);

foreach 将数组元素放入$_,因此无需再次索引数组。 INFILE@infile和循环顶部的整个使用可以简化为

while(<>) {
    my @elements = split(";");

@elements = join(";",@elements); 行看起来不对。循环后的三行可能会更好

print OUTFILE join(";",@elements), "\n";

当对代码进行了明显的改进后,任何真正的错误都应该更容易识别。

确保# Opening and connecting stuff here 还包括use strict; use warnings;

【讨论】:

  • 我知道有些东西并不完美,但我必须像这样处理它。不过,我很感激你的建议!有很大帮助并正在研究它。是的,我正在使用严格和警告:) 它运行时没有错误
【解决方案2】:

它只推送一个值,因为您的哈希只包含一个值。

第一件事是因为你的表有很多值对应一个键,你不应该使用 selectall_hashref 因为如果一行与之前的行具有相同的键,它会覆盖值。

改为使用fetchall_arrayref。它将为您提供对 select 语句输出中每一行的数组引用。

注意:现在使用 fetchall_arrayref 之后,您将很难搜索特定的键,因为您将无法使用简单的存在方法。我的建议是你改变你的 SQL 语句

从文件中读取并对其进行迭代

使用 Split 获取 KEY_REQ

制作语句“Select key,value from $table where key=KEY_REQ”

执行语句

使用 fetchall_arrayref 获取数据

将数据推送到所需的数组

【讨论】:

    【解决方案3】:

    问题在于,当您使用selectall_hashrefif a row has the same key as an earlier row then it replaces the earlier row. 时,请改用selectall_arrayreffetchrow_arrayref

    # Slice => {} lets you use column names instead of array indexes
    my $results = selectall_arrayref($sql_query, { Slice => {} });
    
    # OR
    
    my $sth = $dbh->prepare($sql_query);
    $sth->execute;
    while (my $row = $sth->fetchrow_arrayref) { ... }
    

    一般来说,我建议使用fetchrow_ 方法而不是selectall_fetchall_,因为后者会将您的整个结果集读入内存(尽管在这种情况下,我们需要构建一个包含结果无论如何,所以这并不重要)。

    您需要构建自己的 ID 哈希值:

    my %hash;
    while (my $row = $sth->fetchrow_arrayref) { 
        push @{ $hash{ $row->[0] } }, $row->[1];
    }
    die $sth->errstr if $sth->err; # If you didn't set RaiseError in DBI::connect
    

    散列中的每个键都对应一个值数组。

    我会像这样重写你的其余代码:

    open my $in_fh, "<", "infile" or die $!; # Use lexical file handles
    open my $out_fh, ">", "outfile" or die $!;
    
    while (<$in_fh>) {
        chomp;
        my ($id) = split /;/;
    
        print;
        print join(";", @{ $hash{$id} }) if exists $hash{$id};
        print "\n";
    }
    
    close $in_fh;
    close $out_fh;
    

    【讨论】:

      猜你喜欢
      • 2012-01-05
      • 2017-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-07
      • 2018-06-01
      • 1970-01-01
      • 2014-08-14
      相关资源
      最近更新 更多