I have four tables as follows:
CREATE TABLE IF NOT EXISTS `categories` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
CREATE TABLE IF NOT EXISTS `categories_friends` (
`category_id` int(10) unsigned NOT NULL,
`friend_id` int(10) unsigned NOT NULL,
UNIQUE KEY `category_id` (`friend_id`,`category_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `friends` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(10) unsigned NOT NULL,
`friend_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `user_id` (`user_id`,`friend_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
CREATE TABLE IF NOT EXISTS `ratings` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(10) unsigned NOT NULL,
`category_id` int(10) unsigned NOT NULL,
`title` varchar(255) NOT NULL,
`description` text NOT NULL,
`rating` tinyint(2) unsigned NOT NULL,
`public` tinyint(1) NOT NULL DEFAULT '0',
`created` datetime NOT NULL,
PRIMARY KEY (`id`),
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
I am trying to perform the following query on those tables:
SELECT *
FROM `favred`.`ratings` AS `Rating`
INNER JOIN `favred`.`friends` AS `JFriend`
ON (`JFriend`.`friend_id` = `Rating`.`user_id`)
INNER JOIN `favred`.`categories_friends` AS `JCategoriesFriend`
ON (`JCategoriesFriend`.`category_id` = `Rating`.`category_id`
AND `JCategoriesFriend`.`friend_id` = `JFriend`.`id`)
INNER JOIN `favred`.`categories` AS `JCategory`
ON (`JCategory`.`id` = `Rating`.`category_id`
AND `JCategory`.`id` = `JCategoriesFriend`.`category_id`)
WHERE `JFriend`.`user_id` = 1
AND `Rating`.`user_id` <> 1
AND `JCategory`.`id` IN (4, 14)
GROUP BY `Rating`.`id`
The query above is not working, as it returns no results (although there is data in the tables that should return), what I'm trying to do is to find all the Ratings that were not authored by me (ID:1), but were authored by my Friends, but only if I've selected to view a specific Category for that Friend, with the resulting set being filtered by a given set of specific Categories.
The INNER JOINs loop around through Rating --> Friend --> CategoriesFreind --> Category --> back to Rating.
If I remove the additional portion of the INNER JOIN's ON clauses as follows:
SELECT *
FROM `favred`.`ratings` AS `Rating`
INNER JOIN `favred`.`friends` AS `JFriend`
ON (`JFriend`.`friend_id` = `Rating`.`user_id`)
INNER JOIN `favred`.`categories_friends` AS `JCategoriesFriend`
ON (`JCategoriesFriend`.`friend_id` = `JFriend`.`id`)
INNER JOIN `favred`.`categories` AS `JCategory`
ON (`JCategory`.`id` = `JCategoriesFriend`.`category_id`)
WHERE `JFriend`.`user_id` = 1
AND `Rating`.`user_id` <> 1
AND `JCategory`.`id` IN (4, 14)
GROUP BY `Rating`.`id`
then the query will return results, but because the INNER JOIN joining the CategoriesFriend to the Rating is not being filtered by the 'JCategory'.'id' IN (4, 14) clause, it returns all Ratings by that friend instead of filtered as it should be.
Any suggestions on how to modify my query to get it to pull the filtered results?
And I'm using CakePHP, so a query that would fit into it's unique query format would be preferred although not required.
first ,why are you use the JFriend.id, does it mean something,or is it as the same as user_id?
try this one,the same logic but it's from top to bottom ,I feel:
SELECT * FROM categories as JCategory
INNER JOIN categories_friends as JCategoriesFriend ON JCategoriesFriend.category_id = JCategory.id
INNER JOIN friends AS JFriend ON JFriend.friend_id = JCategoriesFriend.friend_id
INNER JOIN ratings AS Rating ON Rating.user_id = JFriend.friend_id
WHERE JCategory.id IN (4,14) AND JFriend.user_id = 1 AND Rating.user_id <> 1 GROUP BY Rating.id
I got one result from all the data that I made for the testing.
if it does not work also,try make some correct data,maybe the data is not right...
the testing data below:
categories: id | name (14| 141414)
categories_friends: category_id| friend_id (14| 2)
friends: id | user_id | friend_id (4| 1| 2)
ratings: id | user_id | category_id | title (2| 2| 14 | 'haha')
So I wondered if the INNER JOINs were being a little too limiting and specific in their ON clauses. So I thought that maybe a LEFT JOIN would work better...
SELECT *
FROM `favred`.`ratings` AS `Rating`
INNER JOIN `favred`.`friends` AS `JFriend`
ON (`JFriend`.`friend_id` = `Rating`.`user_id`)
LEFT JOIN `favred`.`categories_friends` AS `JCategoriesFriend`
ON (`JCategoriesFriend`.`friend_id` = `JFriend`.`id`
AND `JCategoriesFriend`.`category_id` = `Rating`.`category_id`)
WHERE `JFriend`.`user_id` = 1
AND `JRatingsUser`.`id` IS NULL
AND `Rating`.`user_id` <> 1
GROUP BY `Rating`.`id`
That query worked for me.
I did away with linking to the categories table directly, and linked indirectly through the categories_friends table which sped up the query a little bit, and everything is working great.
Related
I have a query that is executed in 35s, which is waaaaay too long.
Here are the 3 tables concerned by the query (each table is approx. 13000 lines long, and should be much longer in the future) :
Table 1 : Domains
CREATE TABLE IF NOT EXISTS `domain` (
`id_domain` int(11) NOT NULL AUTO_INCREMENT,
`domain_domain` varchar(255) NOT NULL,
`projet_domain` int(11) NOT NULL,
`date_crea_domain` int(11) NOT NULL,
`date_expi_domain` int(11) NOT NULL,
`active_domain` tinyint(1) NOT NULL,
`remarques_domain` text NOT NULL,
PRIMARY KEY (`id_domain`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Table 2 : Keywords
CREATE TABLE IF NOT EXISTS `kw` (
`id_kw` int(11) NOT NULL AUTO_INCREMENT,
`kw_kw` varchar(255) NOT NULL,
`clics_kw` int(11) NOT NULL,
`cpc_kw` float(11,3) NOT NULL,
`date_kw` int(11) NOT NULL,
PRIMARY KEY (`id_kw`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Table 3 : Linking between domain and keyword
CREATE TABLE IF NOT EXISTS `kw_domain` (
`id_kd` int(11) NOT NULL AUTO_INCREMENT,
`kw_kd` int(11) NOT NULL,
`domain_kd` int(11) NOT NULL,
`selected_kd` tinyint(1) NOT NULL,
PRIMARY KEY (`id_kd`),
KEY `kw_to_domain` (`kw_kd`,`domain_kd`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
The query is as follows :
SELECT ng.*, kd.*, kg.*
FROM domain ng
LEFT JOIN kw_domain kd ON kd.domain_kd = ng.id_domain
LEFT JOIN kw kg ON kg.id_kw = kd.kw_kd
GROUP BY ng.id_domain
ORDER BY kd.selected_kd DESC, kd.id_kd DESC
Basically, it selects all domains, with, for each one of these domains, the last associated keyword.
Does anyone have an idea on how to optimize the tables or the query ?
The following will get the last keyword, according to your logic:
select ng.*,
(select kw_kd
from kw_domain kd
where kd.domain_kd = ng.id_domain and kd.selected_kd = 1
order by kd.id_kd desc
limit 1
) as kw_kd
from domain ng;
For performance, you want an index on kw_domain(domain_kd, selected_kd, kw_kd). In this case, the order of the fields matters.
You can use this as a subquery to get more information about the keyword:
select ng.*, kg.*
from (select ng.*,
(select kw_kd
from kw_domain kd
where kd.domain_kd = ng.id_domain and kd.selected_kd = 1
order by kd.id_kd desc
limit 1
) as kw_kd
from domain ng
) ng left join
kw kg
on kg.id_kw = ng.kw_kd;
In MySQL, group by can have poor performance, so this might work better, particularly with the right indexes.
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I have a media center website that I'm working on that has a page that displays media categories. Each category can have multiple media items assigned to it, and each media item can be assigned to multiple categories.
The page contains a text input that must be able to filter the categories that are shown.
What I need to be able to do is get every category that is associated with the current user ($user_id) as well as a media item belonging to that user (unused categories are not displayed). Normally that would be simple enough, but I also have to be able to filter the categories based on fields in other tables associated with the media.
The fields I need to be able to apply the text filter to are as follows:
message_number in the media table
keywords in the media table
speaker_name in the media_speakers table
series_name in the media_series table
book_name in the media_books table
category_name in the media_categories table
As it is now, the query takes several seconds to complete. I'm not a MySQL pro, so I'm sure there must be better ways to do what I need to do here. In case it helps, I'm using MySQLi via PHP. My query has several subqueries, which I'm positive is the cause of the problem, but I didn't know any other way to do what I'm trying to do.
Below are the relevant table structures and the current query. I've included as much info as I can think of that can help someone to help me with this, but if you need more info please just let me know.
The media table (omitting some irrelevant fields) (series,speaker, and book fields contain the ID of a record in their corresponding tables):
`id` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL,
`date` date NOT NULL DEFAULT '0000-00-00',
`message_number` varchar(32) DEFAULT NULL,
`series` int(10) unsigned zerofill NOT NULL DEFAULT '0000000000',
`speaker` int(10) unsigned zerofill NOT NULL DEFAULT '0000000000',
`book` int(10) unsigned zerofill NOT NULL DEFAULT '0000000000',
`keywords` text NOT NULL,
PRIMARY KEY (`id`)
The media_series table:
`id` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL,
`series_name` varchar(255) NOT NULL DEFAULT '',
`cover` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
The media_speakers table:
`id` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL,
`speaker_name` varchar(255) NOT NULL DEFAULT '',
`cover` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
The media_books table:
`id` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,
`book_name` varchar(64) NOT NULL DEFAULT '',
`book_shortname` varchar(10) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
The media_categories table:
`id` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`category_name` varchar(255) NOT NULL DEFAULT '',
`cover` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `id` (`id`)
The media_categories_assoc table:
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(10) unsigned DEFAULT NULL,
`media_id` int(10) unsigned zerofill DEFAULT NULL,
`category_id` int(10) unsigned zerofill DEFAULT NULL,
`marked_for_deletion` int(1) DEFAULT '0',
PRIMARY KEY (`id`)
Finally, the over-complicated query:
SELECT media_categories.id `media_categories.id`,
media_categories.user_id `media_categories.user_id`,
media_categories.category_name `media_categories.category_name`,
media_categories.cover `media_categories.cover`,
(SELECT id
FROM media
WHERE user_id = '$user_id'
AND media_categories.id IN (SELECT category_id
FROM media_category_assoc
WHERE user_id = '$user_id')
ORDER BY `date` DESC
LIMIT 1) `media.id`,
(SELECT `date`
FROM media
WHERE user_id = '$user_id'
AND media_categories.id IN (SELECT category_id
FROM media_category_assoc
WHERE user_id = '$user_id')
ORDER BY `date` DESC
LIMIT 1) `media.date`,
(SELECT series
FROM media
WHERE user_id = '$user_id'
AND media_categories.id IN (SELECT category_id
FROM media_category_assoc
WHERE user_id = '$user_id')
ORDER BY `date` DESC
LIMIT 1) `media.series`,
(SELECT speaker
FROM media
WHERE user_id = '$user_id'
AND media_categories.id IN (SELECT category_id
FROM media_category_assoc
WHERE user_id = '$user_id')
ORDER BY `date` DESC
LIMIT 1) `media.speaker`
FROM media_categories
LEFT JOIN media
ON media.id IN (SELECT media_id
FROM media_category_assoc
WHERE media_id = media.id
AND user_id = '$user_id')
LEFT JOIN media_series
ON media.series = media_series.id
LEFT JOIN media_speakers
ON media.speaker = media_speakers.id
LEFT JOIN media_books
ON media.book = media_books.id
WHERE media_categories.user_id = '$user_id'
AND media_categories.id IN (SELECT category_id
FROM media_category_assoc
WHERE user_id = '$user_id')
AND ( media.title LIKE '%filter_text%'
OR media.message_number LIKE '%filter_text%'
OR media.keywords LIKE '%filter_text%'
OR media_speakers.speaker_name LIKE '%filter_text%'
OR media_categories.category_name LIKE '%filter_text%'
OR media_series.series_name LIKE '%filter_text%'
OR media_books.book_name LIKE '%filter_text%' )
GROUP BY `media_categories.id`
ORDER BY `media.date` DESC
LIMIT 0, 12;
If I have been able to understand the query correctly you try to get some extra information from the most recent media per category for a given user. As far as I can see all of the subqueries in the SELECT-clause can then be moved to the FROM-clause.
Maybe doing it like this could help ?
SELECT media_categories.id,
media_categories.user_id,
media_categories.category_name,
media_categories.cover,
newest_media.id,
newest_media.'date',
newest_media.series,
newest_media.speaker
FROM media_categories
LEFT JOIN media_category_assoc
ON media_categories.id = media_category_assoc.category_id AND media_categories.user_id = media_category_assoc.user_id
LEFT JOIN (
SELECT id, 'date', series, speaker
FROM media
WHERE media.id = media_category_assoc.media_id
ORDER BY `date` DESC
LIMIT 1
) newest_media ON newest_media.user_id = '$user_id'
LEFT JOIN media_series
ON newest_media.series = media_series.id
LEFT JOIN media_speakers
ON newest_media.speaker = media_speakers.id
LEFT JOIN media_books
ON newest_media.book = media_books.id
LEFT JOIN media
ON media.id = media_category_assoc.media_id AND media.user_id = '$user_id'
WHERE media_categories.user_id = '$user_id'
AND ( media.title LIKE '%filter_text%'
OR media.message_number LIKE '%filter_text%'
OR media.keywords LIKE '%filter_text%'
OR media_speakers.speaker_name LIKE '%filter_text%'
OR media_categories.category_name LIKE '%filter_text%'
OR media_series.series_name LIKE '%filter_text%'
OR media_books.book_name LIKE '%filter_text%' )
GROUP BY `media_categories.id`
ORDER BY `media.date` DESC
LIMIT 0, 12;
As I mentioned in my comment, the subqueries can be the bottlenecks in your query. First of all, run an explain select... on your query to check the execution plan.
See the reference manual:
http://dev.mysql.com/doc/refman/5.0/en/explain.html
http://dev.mysql.com/doc/refman/5.0/en/using-explain.html
Now, about the suggestion I made about using temporary tables, I'll take your first subquery to make an example.
You use this:
SELECT
...,
(SELECT id
FROM media
WHERE user_id = '$user_id'
AND media_categories.id IN (SELECT category_id
FROM media_category_assoc
WHERE user_id = '$user_id')
ORDER BY `date` DESC
LIMIT 1),
....
And you can do something like this:
drop table if exists temp_step1;
create temporary table temp_step1
select id
from media
where user_id = #user_id -- I'm assuming you are putting this in a stored procedure
and media_categories.id in (SELECT category_id
FROM media_category_assoc
WHERE user_id = #user_id)
order by `date` desc
limit 1;
Then you can use this temp_step1 table as a row source for your big query.
Notice that this example returns only one row, so there's no point on indexing this. For those temp tables that contain more than one row and which you use in the FROM ... JOIN ... clause of your query, you will need to create indexes at the very least on all the fields you are doing the joins. To do that, after creating the temp table (for example temp_step_X) you should do this:
alter table temp_step_X
add index idx_indexName(field1),
...;
Hope this helps you
I have this query for example (good, it works how I want it to)
SELECT `discusComments`.`memberID`, COUNT( `discusComments`.`memberID`) AS postcount
FROM `discusComments`
GROUP BY `discusComments`.`memberID` ORDER BY postcount DESC
Example Results:
memberid postcount
3 283
6 230
9 198
Now I want to join the memberid of the discusComments table with that of the discusTopic table (because what I really want to do is only get my results from a specific GROUP, and the group id is only in the topic table and not in the comment one hence the join.
SELECT `discusComments`.`memberID`, COUNT( `discusComments`.`memberID`) AS postcount
FROM `discusComments`
LEFT JOIN `discusTopics` ON `discusComments`.`memberID` = `discusTopics`.`memberID`
GROUP BY `discusComments`.`memberID` ORDER BY postcount DESC
Example Results:
memberid postcount
3 14789
6 8678
9 6987
How can I stop this huge increase happening in the postcount? I need to preserve it as before.
Once I have this sorted I want to have some kind of line which says WHERE discusTopics.groupID = 6, for example
CREATE TABLE IF NOT EXISTS `discusComments` (
`id` bigint(255) NOT NULL auto_increment,
`topicID` bigint(255) NOT NULL,
`comment` text NOT NULL,
`timeStamp` bigint(12) NOT NULL,
`memberID` bigint(255) NOT NULL,
`thumbsUp` int(15) NOT NULL default '0',
`thumbsDown` int(15) NOT NULL default '0',
`status` int(1) NOT NULL default '1',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=7190 ;
.
CREATE TABLE IF NOT EXISTS `discusTopics` (
`id` bigint(255) NOT NULL auto_increment,
`groupID` bigint(255) NOT NULL,
`memberID` bigint(255) NOT NULL,
`name` varchar(255) NOT NULL,
`views` bigint(255) NOT NULL default '0',
`lastUpdated` bigint(10) NOT NULL,
PRIMARY KEY (`id`),
KEY `groupID` (`groupID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=913 ;
SELECT `discusComments`.`memberID`, COUNT( `discusComments`.`memberID`) AS postcount
FROM `discusComments`
JOIN `discusTopics` ON `discusComments`.`topicID` = `discusTopics`.`id`
GROUP BY `discusComments`.`memberID` ORDER BY postcount DESC
Joining the topicid in both tables solved the memberID issue. Thanks #Andiry M
You need to use just JOIN not LEFT JOIN and you can add AND discusTopics.memberID = 6 after ON discusComments.memberID = discusTopics.memberID
You can use subqueries lik this
SELECT `discusComments`.`memberID`, COUNT( `discusComments`.`memberID`) AS postcount
FROM `discusComments` where `discusComments`.`memberID` in
(select distinct memberid from `discusTopics` WHERE GROUPID = 6)
If i understand your question right you do not need to use JOIN here at all. JOINs are needed in case when you have many to many relationships and you need for each value in one table select all corresponding values in another table.
But here you have many to one relationship if i got it right. Then you can simply do select from two tables like this
SELECT a.*, b.id FROM a, b WHERE a.pid = b.id
This is simple request and won't create a giant overhead as JOIN does
PS: In the future try to experiment with your queries, try to avoid JOINs especially in MySQL. They are slow and dangerous in their complexity. For 90% of cases when you want to use JOIN there is simple and much faster solution.
I need some help with a MySQL query. I have two tables, one with offers and one with statuses. An offer can has one or more statuses. What I would like to do is get all the offers and their latest status. For each status there's a table field named 'added' which can be used for sorting.
I know this can be easily done with two queries, but I need to make it with only one because I also have to apply some filters later in the project.
Here's my setup:
CREATE TABLE `test`.`offers` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`client` TEXT NOT NULL ,
`products` TEXT NOT NULL ,
`contact` TEXT NOT NULL
) ENGINE = MYISAM ;
CREATE TABLE `statuses` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`offer_id` int(11) NOT NULL,
`options` text NOT NULL,
`deadline` date NOT NULL,
`added` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
Should work but not very optimal imho :
SELECT *
FROM offers
INNER JOIN statuses ON (statuses.offer_id = offers.id
AND statuses.id =
(SELECT allStatuses.id
FROM statuses allStatuses
WHERE allStatuses.offer_id = offers.id
ORDER BY allStatuses.added DESC LIMIT 1))
Try this:
SELECT
o.*
FROM offers o
INNER JOIN statuses s ON o.id = s.offer_id
ORDER BY s.added
LIMIT 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 |
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)