Mysql Помогите облегчить запросы

Forever

Новичок

Есть таблица сообщений A:

id
message (текст)
sentby (id отправителя)
sentto (id получателя)
created (дата создания)


И таблица свойств сообщений для пользователей B (одна запись на каждого участника сообщения) :
Но если пользователь оправляет сообщение самому себе, то сюда отправляется только одна запись,


id
user (id пользователя)
folder (папка сообщения)
message_id (id сообщения)
deleted (удалено ли. логическое значение)

Нужен запрос на удаление сообщений, у которых в таблице B и у отправителя и у получателя
стоит флаг deleted = 1

Все было бы просто, например:

Код:
DELETE FROM `messages` WHERE `id` IN (
    SELECT `message_id`
    FROM `users`
    WHERE `deleted` = 1
    GROUP BY `message_id`
    HAVING COUNT(`message_id`) = 2
)
Если бы не тот факт , что для сообщений самому себе в таблице B одна запись.

И сейчас в голову приходит только такое:

выбрать все сообщения не самому себе, которые удалены у обоих участников
удалить записи по ним в таблице B
Удалить сами сообщения

Код:
SELECT id  FROM  a  WHERE `id` IN (
    SELECT `message_id`
    FROM  b
    WHERE `deleted` = 1
    GROUP BY `message_id`
    HAVING COUNT(`message_id`) = 2
)

DELETE FROM b WHERE message_id IN id, выбранные выше) 

DELETE FROM a WHERE id IN (id, выбранные выше)
Затем выбрать сообщения самому себе
Выбрать сред них те, которые удалены
удалить записи по ним в таблице B
Удалить сами сообщения

Код:
SELECT id  FROM  a  WHERE `id` IN (
    SELECT `message_id`
    FROM `b`
    GROUP BY `message_id`
    HAVING COUNT(`message_id`) = 1
)

SELECT id  FROM  a 
LEFT JOIN b ON a.id = b.message_id 
WHERE
a.`id` IN (id, выбранные выше) 
AND  b.deleted = 1

DELETE FROM b WHERE message_id IN id, выбранные выше) 

DELETE FROM a WHERE id IN ( id, выбранные выше)
Но это же, как бы, жесть полная.
Помогите, пожалуйста, сократить или облегчить запросы
 

fixxxer

К.О.
Партнер клуба
Было бы намного понятнее, если бы ты не описывал словами, а показывал show create table, раз уж все равно перешел потом к реальным запросам.
Если продраться через описание и странные названия столбцов, получается, что соответствия такие

1) users.message_id = messages.id and users.user = messages.sentby and deleted
2) users.message_id = messages.id and users.user = messages.sentto and deleted

Если все так, неясно, что мешает вот так и заджойнить (правда, тогда неясно, накой вообще две таблицы). Если не так, то sqlfiddle показывай.
 

AnrDaemon

Продвинутый новичок
Я бы вообще вынес принадлежность сообщения отдельно.

message_id,user_id,status(sent,received,etc.)

Авторство можно оставить. Для контроля.
 

Forever

Новичок
Было бы намного понятнее, если бы ты не описывал словами, а показывал show create table.
Вот таблица самих сообщений:
Код:
CREATE TABLE `messages` (
 `id` int(255) NOT NULL AUTO_INCREMENT,
 `text` varchar(20000) NOT NULL,
 `from` int(255) NOT NULL,
 `to` int(255) NOT NULL,
 `theme` varchar(60) NOT NULL DEFAULT 'Без темы',
 `date` int(10) NOT NULL,
 `read` tinyint(1) NOT NULL DEFAULT '0',
 PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=62 DEFAULT CHARSET=utf8
И вот та, что содержит информацию о сообщении отдельно для каждого пользователя

Код:
CREATE TABLE `message_info` (
 `id` int(255) NOT NULL AUTO_INCREMENT,
 `user_id` int(255) NOT NULL,
 `message_id` int(255) NOT NULL,
 `folder` char(1) NOT NULL,
 `deleted` tinyint(1) NOT NULL DEFAULT '0',
 PRIMARY KEY (`id`),
 KEY `message_id` (`message_id`),
 CONSTRAINT `message_info_ibfk_1` FOREIGN KEY (`message_id`) REFERENCES `messages` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=103 DEFAULT CHARSET=utf8
Если человек шлет сообщение самому себе, т.е. если и from и to равны, то в message_info добавл\ется только одна запись
 

Forever

Новичок
Если я пишу, например, вот так, то удалю только те сообщения, которые посланы не самому тебе, т.е. по которым две записи в message_info

Код:
DELETE FROM
messages
 WHERE `id` IN (
   SELECT `message_id`
   FROM `message_info`
   WHERE `deleted` = 1
   GROUP BY `message_id`
   HAVING COUNT(`message_id`) = 2
)
если так, то да, я удалю те, которые отправлены самому себе ( у которых в message_info 1 запись) и помечены на удаление, но в то же время затрону и те, в которых участвуют
два человека, и хотя бы у одного из них есть пометка на удаление

Код:
DELETE FROM
messages
 WHERE `id` IN (
   SELECT `message_id`
   FROM `message_info`
   WHERE `deleted` = 1
   GROUP BY `message_id`
   HAVING COUNT(`message_id`) > 1
)
А хотелось бы добиться того, чтобы запрос удалял :
1) сообщения, имеющие в таблице message_info 2 записи и в каждой из них deleted = 1
2)Сообщения, имеющие в таблице message_info 1 запись и у нее deleted = 1
 

fixxxer

К.О.
Партнер клуба
Как я и сказал, с двумя джойнами все нормально будет же.
http://sqlfiddle.com/#!9/67b31/1/0

Это если я правильно понимаю, что в message_info еще подразумевается UNIQUE KEY (user_id, message_id).

На будущее - сам делай такой fiddle, если хочешь, чтобы тебе ответили.
 
Последнее редактирование:
Сверху