Добрый день!
Нужно организовать ленту из подписок пользователя.
Например есть две таблицы:
CREATE TABLE IF NOT EXISTS post (
id_post INT( 10 ) UNSIGNED NOT NULL,
id_cattegory tinyint( 3 ) UNSIGNED NOT NULL, -- ID категории где хранится пост
id_user INT( 10 ) UNSIGNED NOT NULL, -- ID юзера написавшего пост
text text NOT NULL default '',
add_date INT( 10 ) UNSIGNED NOT NULL,
PRIMARY KEY (id_post)
) ENGINE = MYISAM DEFAULT CHARSET = cp1251;
CREATE TABLE IF NOT EXISTS following (
id_following INT( 10 ) UNSIGNED NOT NULL,
id_user INT( 10 ) UNSIGNED NOT NULL,
follow ENUM( 'user', 'cattegory' ) NOT NULL, -- вид подписки (пользователь или категория)
id_follow INT( 10 ) UNSIGNED NOT NULL, -- ID пользователя или категории в зависимости от вида подписки
add_date INT( 10 ) UNSIGNED NOT NULL,
PRIMARY KEY (id_following)
) ENGINE = MYISAM DEFAULT CHARSET = cp1251;
Таблица post хранит посты пользователей
Таблица following хранит подписки пользователей на других пользователей и на категории в которых размещаются посты.
Вообщем пользователь может подписаться на другого пользователя и смотреть его посты, и подписаться на категорию что бы смотреть посты этой категории у себя в ленте.
Теперь мне нужно составить такой запрос, что бы пользователь получал свою ленту постов составленную из всех своих подписок.
В голове следующие:
Перебирать огромную таблицу постов (~миллион записей) и проверять каждую запись на существование на неё подписки в таблице following для конкретного пользователя.
SELECT *FROM post WHERE EXISTS ( SELECT *FROM following WHERE id_user='999' AND ((follow='user' AND id_follow=post.id_user) OR (follow='cattegory' AND id_follow=post.id_cattegory)))
Проблема в том, что это не экономично. Перерывать миллион записей что-бы достать юзеру допустим 5 записей на которые он подписался.
Другой вариант с объединением таблиц и вложенным запросом в FROM.
SELECT post.* FROM post, (SELECT *FROM following WHERE id_user='999') as foll WHERE (foll.follow='user' AND post.id_user=foll.id_follow) OR (foll.follow='cattegory' AND post.id_cattegory=foll.id_follow)
Но это наверно ещё более страшный способ. Как я понимаю, при перекрёстном объединение, если таблица post содержит миллион записей, а получившиеся таблица foll две записи, то после слияния получится два миллиона записей для поиска.
Вообщем прошу совета у SQL ниндзи. Может я что не так делаю.
Отредактированно memba (22.06.2012 17:08:45)