简体   繁体   English

mysql perl选择联接和更新表

[英]mysql perl select join and update tables

I have 3 tables as shown below, what I would like help with is understanding the joins (if needed) to execute the following query: 我有3个表,如下所示,我想要帮助的是理解联接(如果需要)以执行以下查询:

My product is in Product table (id,1) It's also available in Deal Table (product_id,1) it has a tariff_id of 10. Because the length in the Tariff table is 0, I don't update available. 我的产品在“产品”表(id,1)中,在“交易”表(product_id,1)中也可用,它的riff_id为10。由于“关税”表中的长度为0,因此我无法更新。

Product table (id,2). 产品表(id,2)。 It's also available in Deal Table (product_id,2) it has a tariff_id of 15. Because the length in the Tariff table is 24 (>0), I need to update available to 1. 在Deal Table(product_id,2)中也可以使用它,其riffit_id为15。由于Tariff表中的长度为24(> 0),因此我需要更新为1。

Product table (id,3) is in Product Table and Deal Table, but in the Deal Table it has 2 tariffs associated with it (25 and 10). 产品表(id,3)位于产品表和交易表中,但在交易表中有2个与之相关的关税(25和10)。 Again this time because the length of one of the tariffs is 12 (>0), I need to update available to 1. 再次,因为关税之一的长度为12(> 0),我需要将可用关税更新为1。

Exactly the same as above for Product table (id,4). 与产品表(id,4)完全相同。

Product Table (id,5). 产品表(id,5)。 Is not in the Deal Table so no update required. 不在交易表中,因此不需要更新。

Product table
-------------------------
   id   |   pm_available
-------------------------
    1           0
    2           0
    3           0
    4           0
    5           0

Deal Table
------------------------------------------
   id    |    product_id   |    tariff_id
------------------------------------------
   1              1                10
   2              2                15
   3              3                25
   4              3                10
   5              4                20
   6              4                25
   7              4                10

Tariff table
----------------------------
    id     |    length
----------------------------
    10            0
    15            24
    20            0
    25            12

The updated Product Table should look like this 更新后的产品表应如下所示

Product table
-------------------------
   id   |   pm_available
-------------------------
    1           0
    2           1
    3           1
    4           1
    5           0

There are over 3000 products and 1 million deals. 有3000多种产品和100万笔交易。 A product_id can appear in the Deals Table hundreds of times. product_id可以在交易表中出现数百次。 So I thought if I select one product from Product Table pass that into a second query, the second query would check to see if 1) The product existed in the Deals Table. 因此,我想如果我从“产品表”中选择一个产品并将其传递给第二个查询,则第二个查询将检查是否1)该产品存在于“交易”表中。 2) If it exists what tariff is it linked to. 2)如果存在,则链接到什么关税。 3) Check if the length of that tariff was greater than 0, if so, do the update. 3)检查该费率的长度是否大于0,如果是,则进行更新。

I have this current script but it doesn't work correctly, I get updates to 'available' when I shouldn't. 我有此当前脚本,但无法正常工作,如果不可以,我将更新为“可用”。

my $dbh = DBI->connect($dbiconnect,$dbiuser,$dbipass,{AutoCommit=>1,RaiseError=>1,PrintError=>0});
my $shh = $dbh->prepare(q{SELECT id FROM products }) or die $dbh->errstr;
my $ih = $dbh->prepare(q{UPDATE products SET available = ? WHERE id = ?}) or die $dbh->errstr;
my $sh = $dbh->prepare(q{
    SELECT d.id
    FROM deals d
    JOIN tariffs t ON d.tariff_id = t.id
    JOIN products p ON d.product_id = p.id
    WHERE d.product_id = ?
    AND t.length > 1
    LIMIT 0,1
}) or die $dbh->errstr;

$shh->execute or die $dbh->errstr;

my @data;

while (@data = $shh->fetchrow_array()) {

    my $id = $data[0];

    $sh->execute("$id");

    if($sh->rows > 0){
        $ih->execute("1", "$id");
        $ih->finish;

    } else {
        $ih->execute("0", "");
        $ih->finish;

    }
    $sh->finish;

    usleep($delay);
}
$shh->finish;

Any help would be greatly appreciated. 任何帮助将不胜感激。

MySQL will do all of this for you — there is no need to involve Perl or multiple SQL statements. MySQL将为您完成所有这些工作-无需涉及Perl或多个SQL语句。

Like this (untested, because I don't have a MySQL server installed at present). 这样(未经测试,因为我目前没有安装MySQL服务器)。

my $update = $dbh->prepare(<<__SQL__);
UPDATE Product
JOIN Deal ON Product.id = Deal.product_id
JOIN Tariff ON Tariff.id = Deal.tariff_id
SET Product.pm_available = 1
WHERE Tariff.length > 0
__SQL__

$update->execute;

Slight mod to what you were doing, 1st query joins all three tables summing the length from the tariffs table (it will be null or zero if there are none). 稍微修改一下您正在执行的操作,第一个查询将所有三个表连接起来,汇总关税表的长度(如果没有,则为null或零)。 Then iterating through the results updating the products table. 然后遍历结果,更新产品表。

The MYSQL only answer offered earlier assumes you are running this script on the same machine as the mysql server (won't work if you're not). 较早提供的MYSQL唯一答案是假定您将此脚本与mysql服务器在同一台计算机上运行(如果不运行,则无法使用)。 I think it would also have potential problems one of which being that it will not set your available to 0 in any case so once available has been flagged it will never unflag no matter what. 我认为它也会有潜在的问题,其中之一是在任何情况下都不会将您的可用状态设置为0,因此一旦标记了可用状态,无论如何都不会取消标记。

my $dbh = DBI->connect($dbiconnect,$dbiuser,$dbipass,{AutoCommit=>1,RaiseError=>1,PrintError=>0});
my $ih = $dbh->prepare(q{UPDATE products SET available = ? WHERE id = ?}) or die $dbh->errstr;
my $sh = $dbh->prepare(q{
    SELECT p.id,sum(t.length)
    FROM ((products p 
    LEFT JOIN deals d) ON p.id = d.product_id)
    LEFT JOIN tariffs t ON d.tariff_id = t.id)
    GROUP BY p.id;
}) or die $dbh->errstr;

while (my @data = $sh->fetchrow_array()) {
    my $id = $data[0];
    my $length = $data[1];
    if($length > 0){
        $ih->execute("1", "$id");
    }else{
        $ih->execute("0", "$id");
    }
    $ih->finish;
    usleep($delay);
}
$sh->finish;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM