0

次の構造のmysqlテーブルがあります

id  name_id  class_id  currency     date       value  change
1    BILL        A         0     04-01-2013    10.00    0
5    BILL        A         0     04-02-2013     9.90    0
12   FRED        A         0     04-01-2013     8.00    0
13   FRED        B         1     04-02-2013     8.50    0  
22   FRED        B         1     04-03-2013     8.51    0  

、 、が等しいchange場合、その日の値と前の日付の値の差に基づいて列を更新したいと考えています。. . したがって、この小さな抜粋では、行 2 のみが に更新され、行 5が に更新されます。name_idclass_idcurrency-0.100.01

400,000 行あり、すべて自動インクリメントされた ID がありますが、ID はどのような順序でもありません。週末と休日の日付が欠落しているため、連続した日付ではありません。

このようなクエリで変更を表示できるようです

SELECT pd.name_id,
   pd.class_id,
   pd.currency, 
   pd.date,
   pd.value,
   ROUND(pd.nav - (SELECT nav
              FROM price_data as x
              WHERE x.date       < pd.date
              AND x.name_id      = pd.name_id
              AND x.class_id     = pd.class_id
              AND x.currency     = pd.currency 
              ORDER BY price_date DESC
              LIMIT 1),5) as change
FROM price_data as pd

更新を行うためにそれを変更しようとしましたが、mysqlエラーが発生し続け、#1093 - You can't specify target table 'pd' for update in FROM clauseそれでもこれが正しいアプローチであるかどうかわかりません。php を使った方が簡単でしょうか?

UPDATE price_data as pd
SET pd.change = (
   pd.value - (SELECT value
              FROM price_data as x
              WHERE x.date       < pd.date
              AND x.fund_id      = pd.fund_id
              AND x.class_id     = pd.class_id
              AND x.currency     = pd.currency )
)

ご協力いただきありがとうございます。

4

2 に答える 2

0

あなたの仕事は簡単なものではありません。そこで、2 つのリクエスト (1 つの SELECT と 1 つの UPDATE) に分割することにしました。

コードは php で作成され、フィドルで提供されたデータに基づいています。

<?php
try {
      $username = 'user';
      $password = '';
      $conn = new PDO('mysql:host=localhost;dbname=test', $username, $password);
      $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

      $stmt = $conn->prepare('
SELECT pd.id,
   ROUND(pd.value - (SELECT value
              FROM price_data as x
              WHERE x.price_date       < pd.price_date
              AND x.fund_id      = pd.fund_id
              AND x.class_id     = pd.class_id
              AND x.currency_id     = pd.currency_id
ORDER BY x.price_date DESC
LIMIT 1
),5) as `change`
FROM price_data as pd
WHERE
    pd.`value_change`=0
');
      $stmt->execute();

      $result = array();
      while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
            if (!is_null($row["change"]))
            {
                  var_dump($row);
                  $stmt2 = $conn->prepare('
UPDATE
    price_data
SET
    price_data.value_change=:change
WHERE
    price_data.id=:id
');
                  $stmt2->execute($row);
            }
      }


} catch(PDOException $e) {
      echo 'ERROR: ' . $e->getMessage();
}
?>

これにより、マシン上の必要なレコードが更新されました。それがあなたのものでどのように機能したか教えてください。

于 2013-05-21T08:02:38.023 に答える