Добавете колона към Категории, която дава основната категория, в която се намира всяка категория (като основните категории се дават сами). И така:
cat_id | main_cat_id | title
-------+-------------+---------
01 | 01 | Science
0101 | 01 | Medicine
02 | 02 | Sport
Изберете от това на cat_id =main_cat_id, за да намерите основните категории; присъединете се обратно към себе си на left.cat_id =right.main_cat_id, за да намерите дъщерните категории, след това към публикациите на cat_id =cat_id. Групирайте по left.cat_id и проектирайте върху cat_id и count(*).
Опитах това в PostgreSQL 8.4 и не виждам защо това не работи в MySQL, тъй като заявката е доста проста. Моите таблици:
create table categories(
cat_id varchar(40) primary key,
main_cat_id varchar(40) not null references categories,
title varchar(40) not null
)
create table posts (
post_id integer primary key,
cat_id varchar(40) not null references categories,
title varchar(40) not null
)
Моята заявка (групиране по заглавие, а не по ID):
select m.title, count(*)
from categories m, categories c, posts p
where m.cat_id = c.main_cat_id
and c.cat_id = p.cat_id
group by m.title
АКТУАЛИЗАЦИЯ:Аз също имах шанс да направя тази работа с низова операция, както опита OP. Заявката (в стандартно съвместим SQL, както се приема от PostgreSQL, а не на диалекта на MySQL) е:
select m.title, count(*)
from categories m, posts p
where m.cat_id = substring(p.cat_id from 1 for 2)
group by m.title;
Което работи добре. Не мога да предложа смислено сравнение по отношение на скоростта, но планът на заявката за това изглеждаше малко по-опростен от този за двупосочното присъединяване.