Схема / Стратегия и запросы к системе ранжирования - PullRequest
2 голосов
/ 02 июля 2011

В моей базе данных есть следующая схема:

| items | CREATE TABLE `items` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `description` text COLLATE utf8_unicode_ci,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |

| rankings | CREATE TABLE `rankings` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) DEFAULT NULL,
  `item_id` int(11) DEFAULT NULL,
  `rank` int(11) DEFAULT NULL,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |

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

SELECT AVG(r.rank) AS rank, i.* FROM rankings r LEFT OUTER JOIN items i ON r.item_id = i.id GROUP BY i.id ORDER BY rank ASC;

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

1) Построить запрос, чтобы получить отсортированный список для всех пользователей таким образом, чтобы неотмеченные элементы все еще учитывались, но, возможно, добавлялись в конец списка для каждого пользователя, отсортированного по дате создания

2) Когда добавляется новый элемент, добавьте строку в таблице рейтинга для каждого пользователя для нового элемента, поместив его последним в текущем рейтинге

Мысли

Ответы [ 2 ]

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

Я не пользователь MySQL, поэтому один из двух синтаксисов будет работать для вас. Используйте ifNull в расчете AVG.

SELECT AVG(ifNull(r.rank,0)) AS rank, i.* 
  FROM rankings r LEFT OUTER JOIN items i ON r.item_id = i.id
GROUP BY i.id
ORDER BY rank ASC;

Или, если mysql не разрешает вложение таких функций:

SELECT AVG(s.rank) as avg_rank, s.*
  FROM ( SELECT ifNull(r.rank,0) AS rank, i.* 
           FROM rankings r LEFT OUTER JOIN items i ON r.item_id = i.id
         GROUP BY i.id ) as s
ORDER BY avg_rank ASC;

Вы также, вероятно, должны добавить отношение внешнего ключа между rankings.item_id и items.id в определениях таблиц с помощью ON DELETE CASCADE.

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

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

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