简体   繁体   中英

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:

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.

Product table (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.

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). Again this time because the length of one of the tariffs is 12 (>0), I need to update available to 1.

Exactly the same as above for Product table (id,4).

Product Table (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. A product_id can appear in the Deals Table hundreds of times. 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. 2) If it exists what tariff is it linked to. 3) Check if the length of that tariff was greater than 0, if so, do the update.

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.

Like this (untested, because I don't have a MySQL server installed at present).

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). 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). 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.

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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