tags:

views:

102

answers:

1

I'm trying to do a SUM and store it in another table. The SUM is simple :

SELECT award.alias_id, 
       SUM(award.points) AS points
FROM award 
INNER JOIN achiever ON award.id = achiever.award_id

I now want to store that. I figured out how to do it on a row-by-row basis :

UPDATE aliaspoint 
   SET points  = (SELECT SUM(award.points) AS points 
                 FROM award 
           INNER JOIN achiever ON award.id = achiever.award_id
                WHERE achiever.alias_id = 2000) 
 WHERE alias_id = 2000;

I thought something like this might work but I get:

ERROR 1111 (HY000): Invalid use of group function


UPDATE aliaspoint 
INNER JOIN achiever ON aliaspoint.alias_id = achiever.alias_id 
INNER JOIN award ON achiever.award_id = award.id 
SET aliaspoint.points = SUM(award.points)

And some table definitions to help :

mysql> show create table aliaspoint;
| metaward_aliaspoint | CREATE TABLE `aliaspoint` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `alias_id` int(11) NOT NULL,
  `points` double DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `alias_id` (`alias_id`),
  KEY `aliaspoint_points` (`points`)
) ENGINE=MyISAM AUTO_INCREMENT=932081 DEFAULT CHARSET=latin1 |

mysql> show create table achiever;
| metaward_achiever | CREATE TABLE `achiever` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `modified` datetime NOT NULL,
  `created` datetime NOT NULL,
  `award_id` int(11) NOT NULL,
  `alias_id` int(11) NOT NULL,
  `count` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `achiever_award_id` (`award_id`),
  KEY `achiever_alias_id` (`alias_id`)
) ENGINE=MyISAM AUTO_INCREMENT=87784996 DEFAULT CHARSET=utf8 |

mysql> show create table award;
| metaward_award | CREATE TABLE `award` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `points` double DEFAULT NULL,
  PRIMARY KEY (`id`),
) ENGINE=MyISAM AUTO_INCREMENT=131398 DEFAULT CHARSET=utf8 |
A: 

You're missing the GROUP BY clause in:

SET points = (SELECT SUM(award.points) AS points 
                FROM award 
          INNER JOIN achiever ON award.id = achiever.award_id
               WHERE achiever.alias_id = 2000)

There isn't enough information on the AWARD and ACHIEVER tables, so I recommend testing this before updating the UPDATE statement:

  SELECT t.id, -- omit once confirmed data is correct
         a.alias_id, -- omit once confirmed data is correct
         SUM(t.points) AS points 
    FROM AWARD t 
    JOIN ACHIEVER a ON a.award_id = t.id
GROUP BY t.id, a.alias_id

Once you know the summing is correct, update the INSERT statement:

SET points = (SELECT SUM(t.points)
                FROM AWARD t 
                JOIN ACHIEVER a ON a.award_id = t.id
               WHERE a.alias_id = 2000 --don't include if you don't need it
            GROUP BY t.id, a.alias_id)
OMG Ponies
How can I use that in my update?
Paul Tarjan
Thank you, but I don't want to just limit to 2000. I want to do it for all of my 1M rows. Is that possible?
Paul Tarjan
@Paul: Don't include the WHERE clause if you don't need it - refer back to my mention about tuning the SELECT statement first, but mind the correllation between the SELECT and the UPDATE statement.
OMG Ponies
Ah! the secret is to join the inner select with the outer table. `UPDATE aliaspoint ap SET points = (SELECT SUM(t.points) FROM award t JOIN achiever a ON a.award_id = t.id WHERE a.alias_id = ap.alias_id GROUP BY a.alias_id);`
Paul Tarjan