WP
^_^
Ведь HAVING после GROUP BY.
Задачка. Форум. Поиск. Есть две таблицы posts и topics (их поля и параметры описаны ниже).
Нужно выбрать топики (тип, название, описание, последнее сообщение), один или несколько постов составляющих которые (составляющих эти топики) релевантны предложенному запросу. При этом в таблице результатов каждый топик не должен встречаться более одного раза (это могло бы произойти если запросу релевантны несколько постов одной темы).
В форме поиска есть кропка "Показывать Сообщения", если она отмечена, то внутри таблицы с результатами, нужно показать пост данного топика который релевантен запросу, подсветив поисковые слова. А также если он, этот пост, не является первым в теме (if topicstart = 0), то прицеплять при наведении span с изображением первого поста. Прошу прощенья за подробный рассказ.
Казалось бы, всё элементарно:
По поисковому слову "привет", с отмеченой галочкой "Показывать Сообщения" запрос выглядит так:
[sql]
SELECT SQL_CALC_FOUND_ROWS `xE_forum_topics`.*, MAX(MATCH (`xE_forum_posts`.`subject`, `xE_forum_posts`.`body`) AGAINST ('привет' IN BOOLEAN MODE)) AS `relevance`, `xE_forum_topics`.*, `xE_forum_posts`.`id` AS `lastpost`, `xE_forum_posts`.`ctime` AS `lastpost_time`, `xE_forum_posts`.`body`, `xE_forum_posts`.`body_smiles`, `xE_forum_posts`.`topicstart`, `xE_users`.`username` AS `lastposter`, `xE_groups`.`group_tag` AS `lastposter_group_tag`, `t1`.`username` AS `topicstarter`, `t2`.`group_tag` AS `topicstarter_group_tag` FROM `xE_forum_posts` LEFT JOIN `xE_forum_topics` ON `xE_forum_posts`.`topicid` = `xE_forum_topics`.`id` LEFT JOIN `xE_forum_posts` AS `t3` ON `xE_forum_topics`.`lastpost` = `t3`.`id` LEFT JOIN `xE_users` ON `xE_forum_posts`.`aid` = `xE_users`.`id` LEFT JOIN `xE_users` AS `t1` ON `xE_forum_topics`.`aid` = `t1`.`id` LEFT JOIN `xE_groups` ON `xE_users`.`groupid` = `xE_groups`.`gid` LEFT JOIN `xE_groups` AS `t2` ON `t1`.`groupid` = `t2`.`gid` GROUP BY `xE_forum_topics`.`id` HAVING `relevance` > 0 ORDER BY `relevance` DESC LIMIT 0,30
[/sql]
Но GROUP BY выполняется вперед HAVING поэтому поиск, как и следовало ожидать, производится лишь по первому посту темы. А WHERE использовать не можем, т.к. поле `relevance` не хранится в таблице.
Я давно не спал, поэтому плохо соображаю, не подскажите как быть? Не хотелось бы использовать временную таблицу.
Поля таблиц:
CREATE TABLE `xE_forum_topics` (
`id` int(10) unsigned NOT NULL auto_increment,
`section_id` int(11) NOT NULL default '0',
`subject` varchar(100) NOT NULL default '',
`description` varchar(100) NOT NULL default '',
`views` int(11) unsigned NOT NULL default '0',
`ctime` int(11) NOT NULL default '0',
`countposts` int(11) unsigned NOT NULL default '0',
`lastpost` int(11) NOT NULL default '0',
`aid` int(11) NOT NULL default '0',
`guest_username` varchar(100) NOT NULL default '',
`closed` tinyint(1) NOT NULL default '0',
`sticky` tinyint(1) NOT NULL default '0',
`announcement` tinyint(1) NOT NULL default '0',
PRIMARY KEY (`id`),
KEY `section_id` (`section_id`),
FULLTEXT KEY `description` (`description`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251 COMMENT='Forum Topics'
xE_forum_posts | CREATE TABLE `xE_forum_posts` (
`id` int(10) unsigned NOT NULL auto_increment,
`topicid` int(11) NOT NULL default '0',
`topicstart` tinyint(1) NOT NULL default '0',
`replypost` int(10) unsigned NOT NULL default '0',
`aid` int(11) NOT NULL default '0',
`guest_username` varchar(100) NOT NULL default '',
`ip` int(10) unsigned NOT NULL default '0',
`subject` varchar(100) character set utf8 NOT NULL default '',
`body` longtext character set utf8 NOT NULL,
`body_smiles` tinyint(1) NOT NULL default '0',
`ctime` int(11) NOT NULL default '0',
`atime` int(11) NOT NULL default '0',
`timesedit` int(11) NOT NULL default '0',
`showsignature` tinyint(1) NOT NULL default '0',
PRIMARY KEY (`id`),
FULLTEXT KEY `fulltext` (`subject`,`body`)
ENGINE=MyISAM DEFAULT CHARSET=cp1251 COMMENT='Forum Posts' |
Задачка. Форум. Поиск. Есть две таблицы posts и topics (их поля и параметры описаны ниже).
Нужно выбрать топики (тип, название, описание, последнее сообщение), один или несколько постов составляющих которые (составляющих эти топики) релевантны предложенному запросу. При этом в таблице результатов каждый топик не должен встречаться более одного раза (это могло бы произойти если запросу релевантны несколько постов одной темы).
В форме поиска есть кропка "Показывать Сообщения", если она отмечена, то внутри таблицы с результатами, нужно показать пост данного топика который релевантен запросу, подсветив поисковые слова. А также если он, этот пост, не является первым в теме (if topicstart = 0), то прицеплять при наведении span с изображением первого поста. Прошу прощенья за подробный рассказ.
Казалось бы, всё элементарно:
PHP:
$result = $sql->query('SELECT SQL_CALC_FOUND_ROWS'
.' `'.SQL_TBLPREFIX.'forum_topics`.*'
.', MAX(MATCH (`'.SQL_TBLPREFIX.'forum_posts`.`subject`, `'.SQL_TBLPREFIX.'forum_posts`.`body`) AGAINST (\''.sqlescape($str_words).'\' IN BOOLEAN MODE)) AS `relevance`'
.', `'.SQL_TBLPREFIX.'forum_topics`.*, `'.SQL_TBLPREFIX.'forum_posts`.`id` AS `lastpost`'
.', `'.SQL_TBLPREFIX.'forum_posts`.`ctime` AS `lastpost_time`'
.($show_posts?', `'.SQL_TBLPREFIX.'forum_posts`.`body`'
.', `'.SQL_TBLPREFIX.'forum_posts`.`body_smiles`'
.', `'.SQL_TBLPREFIX.'forum_posts`.`topicstart`':'')
.', `'.SQL_TBLPREFIX.'users`.`username` AS `lastposter`'
.', `'.SQL_TBLPREFIX.'groups`.`group_tag` AS `lastposter_group_tag`'
.', `t1`.`username` AS `topicstarter`'
.', `t2`.`group_tag` AS `topicstarter_group_tag`'
.' FROM `'.SQL_TBLPREFIX.'forum_posts`'
.' LEFT JOIN `'.SQL_TBLPREFIX.'forum_topics` ON `'.SQL_TBLPREFIX.'forum_posts`.`topicid` = `'.SQL_TBLPREFIX.'forum_topics`.`id`'
.' LEFT JOIN `'.SQL_TBLPREFIX.'forum_posts` AS `t3` ON `'.SQL_TBLPREFIX.'forum_topics`.`lastpost` = `t3`.`id`'
.' LEFT JOIN `'.SQL_TBLPREFIX.'users` ON `'.SQL_TBLPREFIX.'forum_posts`.`aid` = `'.SQL_TBLPREFIX.'users`.`id`'
.' LEFT JOIN `'.SQL_TBLPREFIX.'users` AS `t1` ON `'.SQL_TBLPREFIX.'forum_topics`.`aid` = `t1`.`id`'
.' LEFT JOIN `'.SQL_TBLPREFIX.'groups` ON `'.SQL_TBLPREFIX.'users`.`groupid` = `'.SQL_TBLPREFIX.'groups`.`gid`'
.' LEFT JOIN `'.SQL_TBLPREFIX.'groups` AS `t2` ON `t1`.`groupid` = `t2`.`gid`'
.' GROUP BY `'.SQL_TBLPREFIX.'forum_topics`.`id`'
.' HAVING `relevance` > 0 ORDER BY `relevance` DESC'
.' LIMIT '.($perpage*$pagenum).','.$perpage);
[sql]
SELECT SQL_CALC_FOUND_ROWS `xE_forum_topics`.*, MAX(MATCH (`xE_forum_posts`.`subject`, `xE_forum_posts`.`body`) AGAINST ('привет' IN BOOLEAN MODE)) AS `relevance`, `xE_forum_topics`.*, `xE_forum_posts`.`id` AS `lastpost`, `xE_forum_posts`.`ctime` AS `lastpost_time`, `xE_forum_posts`.`body`, `xE_forum_posts`.`body_smiles`, `xE_forum_posts`.`topicstart`, `xE_users`.`username` AS `lastposter`, `xE_groups`.`group_tag` AS `lastposter_group_tag`, `t1`.`username` AS `topicstarter`, `t2`.`group_tag` AS `topicstarter_group_tag` FROM `xE_forum_posts` LEFT JOIN `xE_forum_topics` ON `xE_forum_posts`.`topicid` = `xE_forum_topics`.`id` LEFT JOIN `xE_forum_posts` AS `t3` ON `xE_forum_topics`.`lastpost` = `t3`.`id` LEFT JOIN `xE_users` ON `xE_forum_posts`.`aid` = `xE_users`.`id` LEFT JOIN `xE_users` AS `t1` ON `xE_forum_topics`.`aid` = `t1`.`id` LEFT JOIN `xE_groups` ON `xE_users`.`groupid` = `xE_groups`.`gid` LEFT JOIN `xE_groups` AS `t2` ON `t1`.`groupid` = `t2`.`gid` GROUP BY `xE_forum_topics`.`id` HAVING `relevance` > 0 ORDER BY `relevance` DESC LIMIT 0,30
[/sql]
Но GROUP BY выполняется вперед HAVING поэтому поиск, как и следовало ожидать, производится лишь по первому посту темы. А WHERE использовать не можем, т.к. поле `relevance` не хранится в таблице.
Я давно не спал, поэтому плохо соображаю, не подскажите как быть? Не хотелось бы использовать временную таблицу.
Поля таблиц:
CREATE TABLE `xE_forum_topics` (
`id` int(10) unsigned NOT NULL auto_increment,
`section_id` int(11) NOT NULL default '0',
`subject` varchar(100) NOT NULL default '',
`description` varchar(100) NOT NULL default '',
`views` int(11) unsigned NOT NULL default '0',
`ctime` int(11) NOT NULL default '0',
`countposts` int(11) unsigned NOT NULL default '0',
`lastpost` int(11) NOT NULL default '0',
`aid` int(11) NOT NULL default '0',
`guest_username` varchar(100) NOT NULL default '',
`closed` tinyint(1) NOT NULL default '0',
`sticky` tinyint(1) NOT NULL default '0',
`announcement` tinyint(1) NOT NULL default '0',
PRIMARY KEY (`id`),
KEY `section_id` (`section_id`),
FULLTEXT KEY `description` (`description`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251 COMMENT='Forum Topics'
xE_forum_posts | CREATE TABLE `xE_forum_posts` (
`id` int(10) unsigned NOT NULL auto_increment,
`topicid` int(11) NOT NULL default '0',
`topicstart` tinyint(1) NOT NULL default '0',
`replypost` int(10) unsigned NOT NULL default '0',
`aid` int(11) NOT NULL default '0',
`guest_username` varchar(100) NOT NULL default '',
`ip` int(10) unsigned NOT NULL default '0',
`subject` varchar(100) character set utf8 NOT NULL default '',
`body` longtext character set utf8 NOT NULL,
`body_smiles` tinyint(1) NOT NULL default '0',
`ctime` int(11) NOT NULL default '0',
`atime` int(11) NOT NULL default '0',
`timesedit` int(11) NOT NULL default '0',
`showsignature` tinyint(1) NOT NULL default '0',
PRIMARY KEY (`id`),
FULLTEXT KEY `fulltext` (`subject`,`body`)
ENGINE=MyISAM DEFAULT CHARSET=cp1251 COMMENT='Forum Posts' |