Девелоплю для проэкта форум, смесь PHPBB, vBulletin и прочих - крч вбираю всё лучшее из всех форумов Столкнгулся с такой вещью как "Отметить форумы как прочитанное" - появилась загвоздка... КАК это реализуют по умному и при минимум ресурсов (особенно SQL запроса). собственно есть таблицы вида: PHP: CREATE TABLE forums_areas ( far_id int(11) unsigned NOT NULL auto_increment, far_title char(50) NOT NULL default '', far_creation_date datetime NOT NULL, PRIMARY KEY (far_id), KEY far_creation_date (far_creation_date) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED; CREATE TABLE forums ( for_id int(11) unsigned NOT NULL auto_increment, for_far_id int(11) unsigned NOT NULL, for_title char(50) NOT NULL default '', for_creation_date datetime NOT NULL, for_descr char(200) default NULL, for_topics int(11) unsigned NOT NULL default '0', for_messages int(11) unsigned NOT NULL default '0', for_last_frm_id int(11) unsigned NOT NULL default '0', PRIMARY KEY (for_id,for_far_id), UNIQUE KEY for_id (for_id), KEY for_last_frm_id (for_last_frm_id), KEY for_creation_date (for_creation_date), KEY for_far_id (for_far_id) ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED; CREATE TABLE forums_topics ( frt_id int(11) unsigned NOT NULL auto_increment, frt_prf_id int(11) unsigned NOT NULL, frt_for_id int(11) unsigned NOT NULL, frt_creation_date datetime NOT NULL, frt_title char(50) NOT NULL default '', frt_closed enum('no','yes') NOT NULL default 'no', frt_sticky enum('yes','no') NOT NULL default 'no', frt_replyes int(11) unsigned NOT NULL default '0', frt_views int(11) unsigned NOT NULL default '1', frt_last_frm_id int(11) unsigned NOT NULL, PRIMARY KEY (frt_id,frt_prf_id,frt_for_id), KEY frt_creation_date (frt_creation_date), KEY frt_last_frm_id (frt_last_frm_id), KEY frt_replyes (frt_replyes), KEY frt_views (frt_views) ) ENGINE=InnoDB AUTO_INCREMENT=56 DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED; CREATE TABLE forums_messages ( frm_id int(11) unsigned NOT NULL auto_increment, frm_msg text, frm_prf_id int(11) unsigned NOT NULL, frm_creation_date datetime NOT NULL, frm_frt_id int(11) unsigned NOT NULL, frm_for_id int(11) unsigned NOT NULL, PRIMARY KEY (frm_id), KEY frm_creation_date (frm_creation_date), KEY frm_frt_id (frm_frt_id), KEY frm_for_id (frm_for_id) ) ENGINE=InnoDB AUTO_INCREMENT=711 DEFAULT CHARSET=utf8; CREATE TABLE forums_last_readed ( flr_for_id int(11) unsigned NOT NULL, flr_frt_id int(11) unsigned NOT NULL, flr_prf_id int(11) unsigned NOT NULL, flr_frm_id int(11) unsigned NOT NULL, PRIMARY KEY (flr_for_id,flr_frm_id,flr_prf_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED; *_prf_id - связка на ID пользователя. Остальное я думаю опытному глазу понятно будет. Идея такова, что в forums_last_readed запись о прочтении топика вноситься когда пользователь посещает конкретный топик, поэтому если мы отмечаем всё форумы как прочитанные приходиться учитывать что для части топиков записи уже есть, им нужно сделать UPDATE, а вот большей части не будет, поэтому им надо делать INSERT. Да да, я уже слышу ваши крики про REPLACE, вообщем то для одной части я так и сделал - у меня есть один большой форум и аналог Yahoo Groups, для них я сделал так (поля DB немного подругому называються): PHP: /* * $this->group_id - ID группы */ $result = mysql_query('SELECT gfo_id, grt_id, MAX(grm_id) FROM groups LEFT JOIN groups_areas ON grp_id = gar_grp_id LEFT JOIN groups_forums ON gfo_gar_id = gar_id LEFT JOIN groups_topics ON grt_gfo_id = gfo_id LEFT JOIN groups_messages ON grm_grt_id = grt_id WHERE grp_id = '.(int)$this->group_id.' GROUP BY grt_id', $database); $rows = array(); while ($row = mysql_fetch_row($result)){ $rows[] = '('.$row[0].', '.$row[1].', '.$session['auth'].', '.$row[2].')'; } mysql_query('REPLACE groups_last_readed (lsr_gfo_id, lsr_grt_id, lsr_prf_id, lsr_grm_id) VALUES'.implode(',', $rows), $database); Для небольших групп это годиться, но стоит форуму разрастить хотя бы до 100 топиков (что очень быстро), я уже не говорю про большой общий форум, где это дело недели - представляете какого размера будет REPLACE запрос и как он будет долго выполняться... Очень быстро это всё отвалиться, поэтому мне срочно нужна альтернатива, возможно изменение структуры базы, что бы это можно было сделать в один небольшой запрос (можно мега-сложный, главное что бы быстро работало) или поменять структуру так, что бы на каждую пару ФОРУМ-ТОПИК-ЮЗЕР не надо было свою запись - хотя помоему это почти невозможно.. Думаю так же о процедуре так же.. Ваши идеи/предложения. Принимаються любые варианты (кроме смены БД) от лёгкой модификации до полного перелопачивания. Смеха ради попрошу не писать.
REPLACE нет в стандарте и, вроде, нет в PostgreSQL. делать выборку и вставку(REPLACE) можно одним запросом.
Это понятно, но это большой портал, так что совместимость нам полностью побоку. Вообщем народ, я нашел способ: PHP: mysql_query('REPLACE INTO forums_last_readed SELECT for_id, frt_id, '.$session['auth'].', MAX(frm_id) FROM forums LEFT JOIN forums_topics ON frt_for_id = for_id LEFT JOIN forums_messages ON frm_frt_id = frt_id GROUP BY frt_id', $database); Работает на ура P.S. В других базах где нету аналога REPLACE я чуствую такой запрос станет большой головной болью