Подсчет экземпляров в таблице - PullRequest
3 голосов
/ 04 июля 2011

У меня есть эта система тегов для пометки записей в блоге и тому подобное.Теги находятся в одной таблице, содержащей только имя тега и первичный ключ.Затем у меня есть другая таблица с объектами, использующими теги.

Это может выглядеть примерно так:

_________________________________
| tags                          |
--------------------------------|
| id  | name                    |
|-------------------------------|
|  1  | Scuba diving            |
|  2  | Dancing                 |
---------------------------------

_________________________________
| tag_objects                   |
--------------------------------|
| id  | tag  | object           |
|-------------------------------|
|  1  |  2   | 13               |
|  2  |  2   | 18               |
|  3  |  1   | 24               |
---------------------------------

Теперь мне нужно добавить столбец ктаблица тегов, называемая «происшествия» или что-то.Для каждого тега в тегах, вхождения должны быть установлены на количество раз, которое тег используется в tag_objects.

Так что в основном что-то вроде (очевидно, псевдокод):

foreach(tags):
    UPDATE tags
       SET occurrences = (SELECT COUNT(id) 
                            FROM tag_objects 
                           WHERE tag = tags.id);

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

Ответы [ 7 ]

4 голосов
/ 04 июля 2011

Самый простой способ сделать это без каких-либо дополнительных таблиц:

Сначала добавьте дополнительное поле:

mysql> alter table tags add происходит происходит по умолчанию 0;

Затем просто обновите это новое поле, указав количество вхождений.

mysql> обновите теги в левом соединении (выберите тег, количество (id) как cnt из группы tag_objects поtag) в качестве subq для tags.id = subq.tag set происходит = coalesce (subq.cnt, 0);

Обратите внимание на использование левого соединения для обеспечения подсчета всех тегов, даже неиспользованныхиз них.Функция coalesce преобразует NULL в 0.

1 голос
/ 04 июля 2011

Я бы вообще не хотел хранить вычисленные значения в столбцах базы данных - это грязно, может легко выйти из синхронизации и оскорблять божеств нормализации.

Однако, если вам действительно нужен объект базы данных с счетчиком, а не вычисления на лету, я бы создал представление (http://dev.mysql.com/doc/refman/5.0/en/create-view.html), в котором хранится предварительно вычисленное значение, используя SQL, предоставленный Scorpio

CREATE view tag_occurences AS
SELECT t.id, t.name, 
COUNT(*) AS occurrences
FROM tags t
    INNER JOIN tag_objects to
        ON to.tag = tags.id
GROUP BY t.id, t.name
1 голос
/ 04 июля 2011

Если вам действительно не нужно денормализовать ваши данные, вам следует держаться подальше от этого. Подсчет по индексированным столбцам обычно очень быстрый. Я большой поклонник чистых и нормализованных данных; -)

1 голос
/ 04 июля 2011

Вы проделали хорошую работу, ваш запрос должен работать.

Но это приведет к ужасной производительности.Советую воссоздать таблицу:

CREATE TABLE newTags AS
SELECT t.id, t.name, COUNT(*) AS occurrences
FROM tags t
    INNER JOIN tag_objects to
        ON to.tag = tags.id
GROUP BY t.id, t.name

Это будет очень быстро.

0 голосов
/ 04 июля 2011

Для вставки новых строк вы можете использовать такой запрос: INSERT INTO tags VALUES(x,y,z,1) ON DUPLICATE KEY UPDATE occurrences = occurrences+1; Я не проверял синтаксис, но что-то в этом роде.

0 голосов
/ 04 июля 2011

Ваш псевдо-код будет работать точно так, как написано (без цикла foreach).По крайней мере, в Oracle, я предполагаю, что MySQL позволяет вам использовать коррелированный подзапрос в качестве значения.

0 голосов
/ 04 июля 2011

Я думаю, вы получите лучшую производительность, если будете увеличивать и уменьшать значение occurrences в таблице tag_objects триггер вставки / удаления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...