使用多个表复杂的JOIN

时间:2017-04-06 18:23:04

标签: mysql sql perl union concat

例如

我有几个配置文件表,例如

  • music_profile
  • sports_profile
  • art_profile

所有这些表都有匹配的名称,它们都有一个title列。

第二个表包含每个给定个人资料表行的替代标题。

他们的专栏主要是:

id, parent_id, parent_table, alt_title_001, alt_title_002, alt_title_003, alt_title_004, status, created, updated.

我想

  

选择多个列值
  来自music_profile,sports_profile,art_profile
  标题,alt_title_001,alt_title_002,alt_title_003,alt_title_004 就像一个值

我目前可以使用WHERE title LIKEUNION选择列,但我不知道如何在SELECT语句中组合alternate_titles表。

我在下面提供了我当前的代码。 alternate_titles的表格尚未在此处实施。

我不一定想要这个问题的编码解决方案;我只想提示让我继续前进。

sub AdvancedSearchFormResults {
    my $self = shift;
    my $opts = ref $_[0] eq 'HASH' ? shift : {@_};

    my $mode   = shift;
    my $order  = shift;
    my $limit  = shift;

    my @array;
    my $where;
    my $mode = $$opts{mode};

    my $left_join_clause;
    my (@where_stmt, @where_vals, @join);

    if (defined $$opts{platform}) {
        $where = $$opts{platform};
    }
    if ($$opts{'title_like'}) {
        push(@where_stmt, "title like ?");
        push(@where_vals, '%'.$$opts{'title_like'}.'%');
    }
    if ($$opts{'publisher'}) {
        push(@where_stmt, "publisher = ?");
        push(@where_vals, $$opts{'publisher'});
    }
    if ($$opts{'status'}) {
        push(@where_stmt, "status = ?");
        push(@where_vals, $$opts{'status'});
    }

    my $left_join_clause = scalar @join ? join("\n", @join) : "";

    my $where_clause = @where_stmt    ? "WHERE ".join(" AND ", @where_stmt) : "";
    my $order_clause = length($order) ? "ORDER BY $order"                   : "";
    my $limit_clause = length($limit) ? "LIMIT $limit"                      : "";

    my $select_stmt;

    if ($mode eq 'BUILD') {
        $select_stmt = "SELECT 
                            '$where' AS event,
                            ident,
                            title,
                            publisher
                        FROM $where
                          $left_join_clause
                          $where_clause
                          $order_clause
                          $limit_clause";

        my $sth = $schema->prepare($select_stmt) or die $schema->errstr;
        $sth->execute(@where_vals) or die $sth->errstr;

        while (my $row = $sth->fetchrow_hashref()) {
            push(@array, $row);
        }

    }
    elsif ($mode eq 'UNION') {

        my @select_stmts;
        my @platforms       = $self->ProfileTables();
        my $total_platforms = -1;

        foreach my $table (@platforms) {
            $total_platforms++;
            my $stmt = "(SELECT '$table' AS event,ident,title,publisher,status FROM $table $where_clause)";
            push(@select_stmts, $stmt);
        }

        my $select_stmt .= "$select_stmts[0] UNION ALL";
        $select_stmt    .= join(' UNION ALL ', @select_stmts[ 1 .. 28 ]);

        my @new_vals = (@where_vals, (@where_vals) x $total_platforms);

        my $sth = $schema->prepare($select_stmt) or die $schema->errstr;
        $sth->execute(@new_vals) or die $sth->errstr;

        while (my $row = $sth->fetchrow_hashref()) {
            push(@array, $row);
        }
    }
    elsif ($mode eq 'REFRESH') {
        print '
        <div class="alert alert-danger" role="alert">
             <strong>Please fill out at least one field.</strong>
        </div>';
    }

    return @array;
}

下面是代码的实际应用。

这些变量用作示例。这些数据通常通过表格提供。

my $title     = 'Mario';
my $publisher = '';

my %params = (
    title_like => $title,
    publisher  => $publisher,
    status     => 'a',
);

my @results = $results->AdvancedSearchFormResults(\%params);

print Data::Dumper::Dumper(\@results);

自卸车结果

$VAR1 = [
          {
            'ident' => '2109',
            'title' => 'Mario Bros.',
            'publisher' => 'Atari'
          },
          {
            'ident' => '30',
            'title' => 'Mario Bros.',
            'publisher' => 'Atari'
          },
          {
            'publisher' => 'Atari',
            'ident' => '43',
            'title' => 'Mario Bros.'
          },
    ];

1 个答案:

答案 0 :(得分:0)

经过一些头痛和一些激烈的谷歌搜索后,我能够找到解决方案。

我的问题最基本的解决方案是:

my @profiles = ('art', 'music', 'sports');
my @results;
my $blah;
my $sql;

foreach my $profile (@profiles) {
    $sql = "SELECT
                $profile.ident,
                $profile.title,
                $profile.status
             FROM $profile
            LEFT JOIN alternate_titles ON $profile.ident = alternate_titles.parent_ident
             WHERE title like '%$blah%' 
                OR 
                CONCAT_WS(' ',alternate_titles.alt_title_001,alternate_titles.alt_title_002,alternate_titles.alt_title_003,alternate_titles.alt_title_004
                AND alternate_titles.parent_table = '$profile'";
}
my $sth = $schema->prepare($sql) or die $schema->errstr;
$sth->execute() or die $sth->errstr;

while (my $data = $sth->fetchrow_hashref()) {
    push(@results, $data);
}

这在我的代码示例中无法立即实现,但这是一个很好的起点。

我不知道这是有效率的,如果有人有更好的解决方案,我很乐意看到它。