MySQL: обновить строки в таблице путем повторения и объединения с другим

у меня есть стол бумаги

CREATE TABLE `papers` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(1000) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
  `my_count` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  FULLTEXT KEY `title_fulltext` (`title`),
) ENGINE=MyISAM AUTO_INCREMENT=1617432 DEFAULT CHARSET=utf8 COLLATE=utf8_bin

и еще одна таблица link_table

CREATE TABLE `auth2paper2loc` (
  `auth_id` int(11) NOT NULL,
  `paper_id` int(11) NOT NULL,
  `loc_id` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

Идентификатор papers.id из верхней таблицы такой же, как и link_table.paper_id во второй таблице. Я хочу перебрать каждую строку в верхней таблице и подсчитать, сколько раз этот ее идентификатор появляется во второй таблице, и сохранить «счетчик» в столбце «my_count» в верхней таблице.

Пример: Если бумага с tid = 1 = paper_id появляется 5 раз в таблице link_table, то my_count = 5.

Я могу сделать это с помощью скрипта Python, но это приводит к слишком большому количеству запросов, а у меня миллионы записей, поэтому это очень медленно. И я не могу понять правильный синтаксис, чтобы сделать это прямо внутри MySQL.

Это то, что я повторяю в цикле for в Python (слишком медленно):

SELECT count(link_table.auth_id) FROM link_table
WHERE link_table.paper_id = %s

UPDATE papers SET auth_count = %s WHERE id = %s

Может кто-нибудь, пожалуйста, скажите мне, как создать это? Должен быть способ вложить это и поместить прямо в MySQL, чтобы он работал быстрее, не так ли?


person Aufwind    schedule 03.04.2011    source источник


Ответы (2)


Используйте либо:

UPDATE PAPERS
   SET my_count = (SELECT COUNT(b.paper_id)
                     FROM AUTH2PAPERLOC b
                    WHERE b.paper_id = PAPERS.id)

...or:

   UPDATE PAPERS
LEFT JOIN (SELECT b.paper_id,
                  COUNT(b.paper_id) AS numCount
             FROM AUTH2PAPERLOC b
         GROUP BY b.paper_id) x ON x.paper_id = PAPERS.id
      SET my_count = COALESCE(x.numCount, 0)

COALESCE необходим для преобразования NULL в ноль, когда в таблице AUTH2PAPERLOC нет экземпляров PAPERS.id.

person OMG Ponies    schedule 03.04.2011
comment
Count() возвращает 0, если в AUTH2PAPERLOC не найдено ни одного экземпляра papers.id. - person Ronnis; 04.04.2011
comment
@Ronnis / точно, это не требуется в 1-м запросе. Во 2-м (который обычно быстрее) он есть, но была синтаксическая ошибка - person RichardTheKiwi; 04.04.2011
comment
@ Ричард, ага. Когда я еще раз прочитал его ответ, я понял, что комментарий предназначался для второго запроса. - person Ronnis; 04.04.2011

Как это работает для вас?

update papers a
   set my_count = (select count(*) 
                     from auth2paper2loc b
                    where b.paper_id = a.id);
person Ronnis    schedule 03.04.2011