2011-02-02 24 views
1

これは正しい構文で頭を囲むことができません。以下は私のサブクエリについての簡単な英語の説明で、私はそれを実行したいと思う場所で私のクエリです。MySQL INSERT/SELECTサブクエリの構文

mysql_query("INSERT INTO donations(
      tid, 
      email, 
      amount, 
      ogrequest, 
      total 
      ) 
      VALUES (
       '".esc($p->ipn_data['txn_id'])."', 
       '".esc($p->ipn_data['pay_email'])."', 
       ".(float)$amount.", 
       '".esc(http_build_query($_POST))."', 

      Here I want to select the row with the max date, get the value of the "total" column in that row, and add $amount to that value to form the new "total" for my newly inserted row. 

      )"); 

誰でも助けてもらえますか?

答えて

3

本当の答えは、あなたがこの表の列に合計を格納すべきではないです。それは本当に有用な情報ではありません。格納する必要があるのは現在の日付で、SUMとGROUP BYで合計を計算します。頻繁にアクセスする必要がある場合は、値を他の場所にキャッシュします。

なぜ最後の行の前の行に合計が必要ですか?それは無駄なデータであり、簡単にテーブルから再生成することができます。

なぜこの列に合計を保存しますか?このデータはどのような価値があなたのスキーマに追加されますか?ここで注意すべき重要なことは、合計が個々のトランザクションの特性ではないということです。合計は、個々のトランザクションの集約されたサブセットのプロパティです。

また、DECIMALを使用していて、使用していない場合は、MySQLの通貨列タイプにFLOATを使用していないことを確認してください。 FLOATの値は、何をしているかによって丸め誤差が発生する可能性があります。これは、お金がかかるときにリスクを負う理由がないためです。

+0

あなたは正しいです。私が頻繁にアクセスする必要があるため、何度も何度も何度も何度もSUMを何度も計算するというオーバーヘッドについては疑問に思っていました。私は、これらの行をすべて実行する代わりに、最後の行から単一の値を取得するだけで、DBに負荷がかかりにくくなると考えました。どのようなテクニックをキャッシングすることをお勧めしますか? – Jon

+0

これはまったくキャッシュする必要はありません。実際には、MySQLがキャッシュする可能性が高いからです。これが大規模なアプリケーションで行われる通常の方法は、memcached(http:// memcached)のようなものを使用することです。org /)ですが、これを学ぶことを気にしたくなければ、寄付テーブルのトリガによって更新される別のmysqlテーブルに値を格納することで逃げることができます。 – schizodactyl

+0

私はこのルートに行くつもりです。アドバイスをいただきありがとうございました。他の人の回答にも感謝しています。 – Jon

0

私が作成したものを確認するために、MySQLサーバーへのアクセス権を持っていますが、しないでください、この:

INSERT INTO donations 
(
    tid, 
    email, 
    amount, 
    ogrequest, 
    total 
) 
SELECT 
    '".esc($p->ipn_data['txn_id'])."', 
    '".esc($p->ipn_data['pay_email'])."', 
    ".(float)$amount.", 
    '".esc(http_build_query($_POST))."', 
    total + '".esc($amount)."' 
FROM 
ORDER BY date DESC 
LIMIT 1 

代わりに使用しての直接「INSERT INTO(...)VALUES(...) "私は" INSERT INTO(...)SELECT ... "を使いました。 SELECTステートメントは、最も日付の高い行(ORDER BY日付DESC LIMIT 1)を取得し、合計フィールドにアクセスして$ amountの値を加算します。

0
mysql_query("INSERT INTO donations(
      tid, 
      email, 
      amount, 
      ogrequest, 
      total 
      ) 
      VALUES (
       '".esc($p->ipn_data['txn_id'])."', 
       '".esc($p->ipn_data['pay_email'])."', 
       ".(float)$amount.", 
       '".esc(http_build_query($_POST))."', 
       (select max(total) from donations) + ".(float)$amount." 




      )"); 
0

あなたのサブクエリは、次のようになります。もちろん

SELECT total 
FROM donations 
WHERE tid = <x> 
ORDER BY date DESC 
LIMIT 1 

これは、あなたのテーブルにdate列を持っていることが必要です。このクエリを実行した場合(外部クエリを使用していない場合)、tid = <x>の最新の合計値を含む単一の列の結果が返されます。

テーブルにまだtxn = <x>の行がない場合、明らかに行が返されません。 INSERT文のサブクエリとして使用する場合は、NULLをチェックして数字の0(ゼロ)に置き換える必要があります。これはIFNULL()があなたにできることです。

これを組み合わせると、あなたがすでに持っているもの:

mysql_query("INSERT INTO donations(
      tid, 
      email, 
      amount, 
      ogrequest, 
      total 
      ) 
      VALUES (
       '".esc($p->ipn_data['txn_id'])."', 
       '".esc($p->ipn_data['pay_email'])."', 
       ".(float)$amount.", 
       '".esc(http_build_query($_POST))."', 
       IFNULL(SELECT total 
       FROM donations 
       WHERE id = ".esc(p->ipn_data[txn_id']." 
       ORDER BY date DESC 
       LIMIT 1),0) + ".esc($p->ipn_data['value'] 
      )");