Спасибо за участие. Думаю задача довольно стандартная, но почему то готового варианта нагуглить не удалось.
Сразу сорри за большую месагу, основное в ней дапм.
База
CREATE TABLE IF NOT EXISTS `art2tag` (
`article_id` int(10) unsigned NOT NULL,
`tag_id` int(10) unsigned NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO `art2tag` (`article_id`, `tag_id`) VALUES
(1, 1),
(1, 2),
(2, 1),
(2, 3),
(3, 1),
(3, 2),
(4, 3),
(4, 4);
CREATE TABLE IF NOT EXISTS `articles` (
`article_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`category_id` int(10) unsigned NOT NULL,
`views` int(10) unsigned NOT NULL,
PRIMARY KEY (`article_id`),
KEY `ctg_views` (`category_id`,`views`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
INSERT INTO `articles` (`article_id`, `category_id`, `views`) VALUES
(1, 1, 100),
(2, 1, 100),
(3, 2, 50),
(4, 2, 100);
CREATE TABLE IF NOT EXISTS `tags` (
`tag_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(30) NOT NULL,
PRIMARY KEY (`tag_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
INSERT INTO `tags` (`tag_id`, `name`) VALUES
(1, 'tag1'),
(2, 'tag2'),
(3, 'tag3'),
(4, 'tag4');
========================================
Оригинальный запрос с поиском наиболее популярных статей в каждой категории. Минус - выводит 2 статьи из одной категории если они имеют одинаковый рейтинг. Но это легко решается уже на стороне скрипта.
SELECT a.article_id, a.views
FROM articles AS a
JOIN (
SELECT category_id, max( views ) AS max_views
FROM articles
GROUP BY category_id
) AS v ON ( a.category_id = v.category_id )
WHERE a.views = v.max_views
===========
Задача - вывести статьи относящиеся к текущей статье на основе имеющихся тагов.
Сразу был отброшен вариант с "умным" поиском тагов, аля большинство статей с тагом А, так же имеют таг Б, возможно юзеру будет интересно что-то из тага Б. Возможно кто-то сможет реализовать и это, но мне кажется задача будет довольно сложной.
Сейчас делаю вот так (пример для статьи 1 из дампа выше)
explain select * from `articles` join (select article_id, count(*) as cnt from `art2tag` where tag_id in (1,2) group by article_id order by cnt desc limit 10) as t on t.article_id = `articles`.article_id
where articles.article_id != 1
Explain
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3 Using where
1 PRIMARY articles eq_ref PRIMARY PRIMARY 4 t.article_id 1
2 DERIVED art2tag ALL NULL NULL NULL NULL 8 Using where; Using temporary; Using filesort