使用csv中的键可以使用dbi检索相应的多个键及其值

时间:2014-01-08 15:36:09

标签: mysql perl csv dbi

对不起标题,不知道更好的描述方式。我现在有点陷入困境,可以使用一些帮助。

我正在尝试使用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);

3 个答案:

答案 0 :(得分:0)

这对线重复了一些工作:

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;

答案 1 :(得分:0)

问题在于,当您使用selectall_hashref时,if 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;

答案 2 :(得分:0)

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

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

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

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

  

从文件中读取并迭代它

     

使用Split获取KEY_REQ

     

Make语句“选择键,值来自$ table,其中key = KEY_REQ”

     

执行声明

     

使用fetchall_arrayref

获取数据      

将数据推送到所需的数组