2011-02-02 157 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计算总数。如果这是您需要经常访问的内容,请将值缓存到其他位置。

为什么你需要在最后一行之前的任何行中的总数?这只是浪费的数据,并且可以从表格中轻松重新生成。

为什么要将总数存储在此列中。这些数据为您的架构添加了什么价值?这里要注意的重要一点是,总数不是单个交易的财产。总数是个别事务的聚集子集的属性。

另外 - 确保你在MySQL中使用DECIMAL而不是FLOAT作为你的货币列类型,如果你不是。 FLOAT值可能会导致舍入错误取决于您正在做什么,这是在涉及金钱时没有理由冒险的事情。

+0

你是对的。我这样做的唯一原因是因为我需要经常访问它,并且想知道在数百行中不断计算SUM的开销。我想,不必遍历所有这些行,我可以从最后一行获得单个值,这对数据库来说应该不那么紧张。你会推荐什么技术来缓存它? – Jon 2011-02-02 17:57:25

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 date 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'] 
      )");