I had some weirdness with MySQL today… Updating on a duplicate key error works like a charm: it updates the row which violates with the key and everybody is happy!

Well, actually I’m not… I encountered this problem today. I had a table with a number and an average and the table named averages looked like this:

|-----------------------------|
|      id |  number | average |
|-----------------------------|
|       1 |       1 |       0 |
|       2 |       4 |    0.25 |
|       3 |       2 |     0.5 |
|-----------------------------|

Now let’s say I wanted to increment id 1 with number=2 and an average=1, normally I would use the following query:

UPDATE `averages` SET `number`=`number`+2, `average`=(((`average`*`number`)+(1*2))/(`number`+2)) 
WHERE `id`='1';

This would update the table and set the number to 3 and average to 0.6666667. This worked fine till I added this to a cronjob which calculates averages from large quantities of rows. Since I would not know the identifiers upfront I changed the query to an INSERT query with a ON DUPLICATE KEY UPDATE part which updates when we already have a row for the identifier, so I came up with this:

INSERT INTO `averages` VALUES (1, 2, 1) ON DUPLICATE KEY UPDATE `number`=`number`+2, 
`average`=(((`average`*`number`)+(1*2))/(`number`+2))

But, as I found out later, this doesn’t work the same way as the UPDATE query: the ON DUPLICATE KEY UPDATE does not write itself to a single UPDATE query, but rather to two seperate UPDATE queries. This means that the query will be written to this:

UPDATE `averages` SET `number`=`number`+2 WHERE `id`='1';
UPDATE SET `average`=(((`average`*`number`)+(1*2))/(`number`+2)) WHERE `id`='1';

Can you identify the problem I encountered here? And perhaps guess what the average column was set to?? 😉