Приветствую, гуру оптимизации.
Суть следующая:
На сайте есть система диалогов. Есть диалоги между пользователями (from>0, to>0). Есть система групповых диалогов (from>0, to<0). Структура таблиц:
CREATE TABLE `dialogs` (
`id` int(25) NOT NULL AUTO_INCREMENT,
`user` int(11) NOT NULL,
`title` varchar(512) COLLATE utf8_unicode_ci NOT NULL, # Заполнено только у владельца
`owner` enum('0','1') COLLATE utf8_unicode_ci NOT NULL DEFAULT '0', # Показатель, владелец ли данного диалога
`deleted` enum('0','1') COLLATE utf8_unicode_ci NOT NULL DEFAULT '0', # Исключён ли данный пользователь из диалога, если исключён владелец - диалог удалён у всех
PRIMARY KEY (`id`,`user`),
KEY `user` (`user`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `messages` (
`from` int(15) NOT NULL, # Отправитель
`to` int(25) NOT NULL, # >0 - персональное, <0 - групповое
`text` text COLLATE utf8_unicode_ci NOT NULL,
`time` datetime NOT NULL,
`deleted_from` enum('0','1') COLLATE utf8_unicode_ci NOT NULL DEFAULT '0', # Удалено ли сообщение отправителем (в групповом диалоге - у всех)
`deleted_to` enum('0','1') COLLATE utf8_unicode_ci NOT NULL DEFAULT '0', # Удалено ли сообщение получателем, в групповом диалоге не используется
`unread` enum('0','1') COLLATE utf8_unicode_ci NOT NULL DEFAULT '1', # Флаг "нового" сообщения
PRIMARY KEY (`from`,`to`,`time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Задача —
получить количество непрочитанных сообщений для текущего пользователя (для вывода в строке меню «новые сообщения (N)»), без учёта отправленных им же, и удалённых.
Мой воспалённый мозг родил следующее:
Database::query($new_messages_statement,array('u'=>User::$self['id']));
Statement:
select count(*) as count from `messages` where # Получаем количество
`unread`='1' and # Непрочитанные
`from`!=:u and # Не от самого себя
(
(
`to`=:u and # Написанные мне
`deleted_to`='0' # И не удалённые мной
) or ( # Или...
`deleted_from`='0' and # Которые не удалены владельцем диалога
`to` in # В диалогах...
(
select -(`id`) from `dialogs` where # Получаем список диалогов
`deleted`='0' and # Не удалённых
`owner`='1' and # Основная запись
`id` in
(
select `id` from `dialogs` where # Диалоги
`user`=:u and # В которых я включен
`deleted`='0' # И из которых меня не удалили
)
)
)
)
Оно работает так, как надо, но, похоже, что я делаю что-то не совсем правильно…
Наставьте меня на путь истинный, о гуру SQL! :)