а студент-двоечник.
Категории и тэги лежат в одной таблице. Зачем — непонятно, но это ещё фигня. Таблица выглядит так:
CREATE TABLE `wp_terms` ( `term_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(200) NOT NULL DEFAULT '', `slug` varchar(200) NOT NULL DEFAULT '', `term_group` bigint(10) NOT NULL DEFAULT '0', PRIMARY KEY (`term_id`), UNIQUE KEY `slug` (`slug`), KEY `name` (`name`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8
Что такое term_group — загадка природы, там у всех записей 0.
slug — это URL-encoded name. Им лень было при обработке запросов в /tag/ и /category/ сделать url-decode и поискать по имени, лучше сделать лишнее поле. Причём поле это такой же длины, как и name, а один неанглоязычный символ из name в url-encoded виде занимает 6 байт, например буква “л” выглядит в slug как %d0%bb . А вот почему slug сделан уникальным ключом, а name неуникальным — загадка природы.
А тип записей в wp_terms вообще отсутствует. Он ВНЕЗАПНО лежит в другой таблице:
CREATE TABLE `wp_term_taxonomy` ( `term_taxonomy_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `term_id` bigint(20) unsigned NOT NULL DEFAULT '0', `taxonomy` varchar(32) NOT NULL DEFAULT '', `description` longtext NOT NULL, `parent` bigint(20) unsigned NOT NULL DEFAULT '0', `count` bigint(20) NOT NULL DEFAULT '0', PRIMARY KEY (`term_taxonomy_id`), UNIQUE KEY `term_id_taxonomy` (`term_id`,`taxonomy`), KEY `taxonomy` (`taxonomy`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8
Вот в ней в поле taxonomy хранит тип записи. В текстовом виде: “category”, “post_tag” или “link_category”. И в сочетании с term_id оно составляет уникальный ключ. То есть, если попытаться создать и категорию, и тэг с одинаковым именем, то в wp_terms будет только одна запись, а в wp_term_taxonomy – две, с одинаковым term_id. Но это такая редкость, что экономить единичные записи в таблице, существенно усложняя при этом поиск по имени (join двух таблиц вместо простого поиска в одной) — это идиотизм.
Что есть parent — я вообще не понял, там всегда 0. А count (руки оторвать за использование названий стандартных функций в качестве имён полей) по идее должен хранить количество постов, привязанных к данной категории или тэгу. И для большинства записей это действительно так. Но иногда..
mysql> select term_taxonomy_id, count from wp_term_taxonomy where term_taxonomy_id = 1; +------------------+-------+ | term_taxonomy_id | count | +------------------+-------+ | 1 | 1933 | +------------------+-------+ mysql> select count(*) from wp_term_relationships where term_taxonomy_id = 1; +----------+ | count(*) | +----------+ | 3708 | +----------+
Ничего общего.. И даже если посчитать только опубликованные посты (исключить черновики и старые версии), всё равно не совпадает:
mysql> select count(*) from wp_term_relationships r join wp_posts p on r.object_id=p.ID where r.term_taxonomy_id = 1 and p.post_status='publish'; +----------+ | count(*) | +----------+ | 1936 | +----------+
Оригинал этой записи в личном блоге.