Я написал сложный запрос UPDATE, и он работает, но выглядит угрожающе. Вот что я пытаюсь сделать:
В каждой теме пользователь 'Bob123' разместил анонимно. Когда вы публикуете анонимно в теме, вы получаете уникальный анонимный индекс для этой темы.
Скажем, я хочу объединить две темы. У Bob123 разные индексы анонов в обеих темах, поэтому его уникальный индекс анонов не будет уникальным. У меня есть только две части данных для работы: $ topic_id, идентификатор темы, с которой вы объединяетесь, и $ post_id_list, все идентификаторы сообщений, которые были объединены.
Я хочу обновить все записи anonymous_index для каждого отдельного поста poster_id в этой теме. Этот anonymous_index должен быть исходным индексом, который они имели в теме, до того, как в него была включена другая тема.
Первый запрос SELECT сначала выбирает анон-индексы перемещенных сообщений.
Внешний запрос SELECT получает анон-индекс первого не объединенного поста (если он равен > 0
) из этих объединенных постеров в теме и выбирает индекс анонного слияния из первого запроса.
Затем я обновляю его. Везде, где анонный индекс этих постеров в этой теме не равен старому индексу, я обновляю его.
Есть что-то простое, что я здесь упускаю? Мне не нравится тот факт, что у меня есть подзапрос в подзапросе.
Сначала я использовал HAVING MIN(anonymous_index) <> MAX(anonymous_index)
вместе с AND post_id NOT IN ($merged_post_list)
, чтобы выбрать список идентификаторов плаката, который необходимо обновить, и индекс unonged anon, но он вернул 0 строк с этим. Если объединенная публикация ДО всех оригинальных публикаций (и имеет больший индекс анона), то минимальный индекс анона будет соответствовать максимальному индексу для этого постера. Поэтому создание другого подзапроса исправило это ...
$merged_post_list = implode(',', $post_id_list);
...
UPDATE " . POSTS_TABLE . " AS p
INNER JOIN ( SELECT p.post_id, p.anonymous_index AS old_index,
merged.poster_id, merged.anonymous_index AS new_index
FROM " . POSTS_TABLE . " AS p,
( SELECT poster_id, anonymous_index
FROM " . POSTS_TABLE . "
WHERE post_id IN ($merged_post_list)
AND topic_id = $topic_id
AND anonymous_index > 0
) AS merged
WHERE p.post_id NOT IN ($merged_post_list)
AND p.topic_id = $topic_id
AND p.anonymous_index > 0
AND p.poster_id = merged.poster_id
GROUP BY merged.poster_id
) AS postdata
SET p.anonymous_index = postdata.old_index
WHERE p.topic_id = $topic_id
AND anonymous_index > 0
AND anonymous_index <> postdata.old_index
AND p.poster_id = postdata.poster_id
post_id - основной индекс, poster_id и topic_id - также индексы.
Вот пример поведения:
До слияния:
|post_id_____poster_id_____anonymous_index|
| 11 | 3 | 2 |
| 12 | 22 | 1 |
| 14 | 22 | 1 |
| 15 | 3 | 2 |
После слияния:
|post_id_____poster_id_____anonymous_index|
| 10 | 22 | 4 |
| 11 | 3 | 2 |
| 12 | 22 | 1 |
| 13 | 3 | 4 |
| 14 | 22 | 1 |
| 15 | 3 | 2 |
| 16 | 22 | 4 |
После ОБНОВЛЕНИЯ (вышеуказанный запрос):
|post_id_____poster_id_____anonymous_index|
| 10 | 22 | 1 |
| 11 | 3 | 2 |
| 12 | 22 | 1 |
| 13 | 3 | 2 |
| 14 | 22 | 1 |
| 15 | 3 | 2 |
| 16 | 22 | 1 |
РЕДАКТИРОВАТЬ: я сделал следующий индекс и альтернативный запрос SELECT, чтобы избежать двух подзапросов, как эти тарифы ?:
(topic_id, poster_id, anonymous_index, post_id)
SELECT p.post_id, p.anonymous_index AS old_index,
merged.poster_id, merged.anonymous_index AS new_index
FROM " . POSTS_TABLE . " AS p,
" . POSTS_TABLE . " AS merged
WHERE p.topic_id = $topic_id
AND p.anonymous_index > 0
AND p.post_id NOT IN ($post_list)
AND p.poster_id = merged.poster_id
AND merged.topic_id = $topic_id
AND merged.anonymous_index > 0
AND merged.post_id IN ($post_list)
GROUP BY merged.poster_id
ORDER BY NULL