使用全文查询在mysql中进行子查询

时间:2011-12-22 06:49:45

标签: mysql perl full-text-search subquery

我正在尝试查询数据库。我已经有一个文件,其中包含整个数据库中的一些主键。现在我想过滤这些主键,只获得那些同意"其他条件"的主键。我的主键与数据库中的摘要相关联。摘要是全文索引的。现在我想考虑使用给定主键的摘要,寻找我的"其他条件(术语)"在那些摘要中,如果它的存在,我想拉出他们的主键(从文件中将是相同的)。我的"其他条件"是另一个带有术语列表的文件。我想获得在给定主键中包含这些术语的摘要。

我的全文搜索是这样的:

while(<FILE1>){
$PK = $_;
foreach $foo(@foo){
my $sth = $dbh->prepare(qq{
   SELECT value
     FROM value_table
    WHERE MATCH (column_text_indexed) AGAINST (? IN BOOLEAN MODE)
}) AND primary_key=$PK;

$sth->execute(qq{+"$foo"});
}
}

其中$ PK来自我已有的主键列表。 $ foo将是我正在寻找的条款(条件2)的列表。

通常情况下,我可以运行$ PK次数$ foo的查询号。但是我通过子查询了解了一些关于优化的内容,在那里我不会运行我的查询#$ PK times#$ foo。这将摆脱内循环,但仍将形成每个$ PK与文件2中@foo的每个术语的组合。如下所示:

while(<FILE1>){
$PK = $_;
   my $sth = $dbh->prepare(qq{
   SELECT value
     FROM value_table
    WHERE MATCH (column_text_indexed) AGAINST (**SUB QUERYING HERE**)
}) AND primary_key=$PK;

$sth->execute(qq{+"$foo"});

}

我不知道该怎么做。我的语法可能有问题。我想知道如何为全文搜索和子查询编写代码。我希望这比直接查询组合更有效。非常感谢任何帮助。

3 个答案:

答案 0 :(得分:1)

你的语法看起来很狡猾。我想你的意思是:

while(<FILE1>){
    $PK = $_;

    foreach $foo (@foo){

         my $sth = $dbh->prepare(qq{
                     SELECT value
                     FROM value_table
                     WHERE MATCH (column_text_indexed)
                       AGAINST (**SUB QUERYING HERE**)
                     AND primary_key=$PK });           # '})' after AND clause

         $sth->execute(qq{ $foo });
     }
}

但是为什么不在这种情况下使$PK成为另一个参数(并使用最佳实践)? :

while ( my $PK = <FILE1> ) {

    chomp $PK;  # Remove trailing newline

    foreach my $foo ( @foo ) {   # Lexical $foo

        my $sth = $dbh->prepare( qq{
                         SELECT value
                         FROM value_table
                         WHERE MATCH (column_text_indexed)
                           AGAINST (**SUB QUERYING HERE**)
                         AND primary_key=? });             # Extra placeholder

        $sth->execute( $foo, $PK );
    }
}

答案 1 :(得分:1)

我认为你不需要使用子查询。但是你仍然可以通过组合匹配字符串来摆脱内部循环。

my $against = join ' ', map {qq/"$_"/} @foo;
while (my $PK = <FILE1>) {
    chomp $PK;

    my $sth = $dbh->prepare(qq{
       SELECT value
         FROM value_table
        WHERE primary_key = ?
          # no '+' so it can match against at least one of the words in the list
          AND MATCH (column_text_indexed) AGAINST (? IN BOOLEAN MODE)
    });
    $sth->execute($PK, $against);

<强>更新

我修改了它并完全从循环中删除了查询。

my @primary_keys;
while (my $PK = <FILE1>) {
    chomp $PK;
    push @primary_keys, $PK;
}

my $PK_list = join ',', map {qq/'$_'/} @primary_keys;
my $against = join ' ', map {qq/"$_"/} @foo;

my $sth = $dbh->prepare(qq{
   SELECT value
     FROM value_table
    # placeholders can only represent single scalar values so $PK_list can't be bound
    WHERE primary_key IN ($PK_list)
      # no '+' so it can match against at least one of the words in the list
      AND MATCH (column_text_indexed) AGAINST (? IN BOOLEAN MODE)
});
$sth->execute($against);

# continue with fetching the rows
...;

答案 2 :(得分:1)

如果您想要效率,我建议使用最少的数据库事务和操作。所以在这种情况下,我认为最好的选择是从主数据库中获取摘要,然后通过在珍珠或任何其他标准语言代码中进行简单的字符串搜索来搜索该摘要中的术语。我不太确定您的条款清单的长度。但如果可能的话,你可以将它保存在标准的数据结构中,如数组或列表。数据库中的相同操作肯定会花费更多的时间。我对珍珠语法不太好,所以我正在编写算法。

对于PK中的所有术语,将抽象作为字符串变量获取:

对于数组/列表中的每个术语:在包含abstract的字符串变量中查找该术语。如果找到,请将PK添加到新文件中。

继续下一个pk。

如果没有找到,则在数组/列表中继续下一个术语。