Не возможно использовать для обновления таблицу, в которой производишь выборку
Понадобилось ежесуточно высчитывать размер шрифта для оформления вывода жанров на Кинсбурге. И столкнулся с проблемой, что нельзя выбирать данные из таблицы, которая участвует в обновлении данных.
Вот примеры запросов
Пробуем в лоб:
update `categories` set `size` = (`count` / ((max(`count`) - min(`count`)) / 10)); ERROR 1111 (HY000): Invalid use of group function
Попробуем вложенный селект:
update `categories` set `size` = (select (`count` / ((max(`count`) - min(`count`)) / 10)) from `categories`); ERROR 1093 (HY000): You can't specify target table 'categories' for update in FROM clause
Попробуем жоин:
update `categories` as `c1` JOIN `categories` as `c2` using(`category_id`) set `c1`.`size` = (`c2`.`count` / ((max(`c2`.`count`) - min(`c2`.`count`)) / 10)); ERROR 1111 (HY000): Invalid use of group function
По отдельности все работает
Выводим "размер шрифта":
select (`count` / ((max(`count`) - min(`count`)) / 10)) from `categories`; +--------------------------------------------------------+ | (`count` / ((max(`count`) - min(`count`)) / 10)) | +--------------------------------------------------------+ | 3.47826087 | +--------------------------------------------------------+ 1 row in set (0.00 sec)
Обновляем поле с размером шрифта:
update `categories` set `size` = 3.47826087; Query OK, 0 rows affected (0.00 sec) Rows matched: 21 Changed: 0 Warnings: 0
Решение
Погуглив, и поломав голову с disc'ом, я пришел к следующему решению, представленное ниже.
Я решил выделить вычисление процента в переменную @percent, далее создал вьюху для таблицы "categories" и жойню таблицу с вьюхой:
-- создаем коэффициент деления set @percent = (select (max(`count`) - min(`count`)) / 10 from `categories`); -- создаем вьюху create view `categories_view` as select `category_id`, `count` from `categories`; -- жойним таблицу и вьюху, обновляя данные update `categories` as `c` join `categories_view` as `cv` using(`category_id`) set `c`.`size` = `cv`.`count` / @percent;
Вот и все, приятного манокурения :)
UPD: Создадим процедуру и евент для этого события
/* Создаем вьюху и процедуру для установки размеров шрифта */ use kinsburg; /* создаем вьюху */ CREATE VIEW `categories_view` AS SELECT `category_id`, `count` FROM `categories`; /* создаем процедуру */ delimiter // DROP PROCEDURE IF EXISTS `updateCategorySize`// CREATE PROCEDURE `updateCategorySize` () BEGIN /* создаем коэффициент деления */ SET @percent = (SELECT (max(`count`) - min(`count`)) / 10 FROM `categories`); /* жойним таблицу и вьюху, обновляя данные */ UPDATE `categories` AS `c` JOIN `categories_view` AS `cv` USING(`category_id`) SET `c`.`size` = `cv`.`count` / @percent; END// delimiter ; /* создаем евент для вызова процедуры раз в сутки */ CREATE DEFINER = kinsburg@localhost EVENT `updateCategorySizeEvent` ON SCHEDULE EVERY 1 DAY DO CALL updateCategorySize;
Комментарии
Adw0rd, Насколько я понимаю что после выполнения данной процедуры, что после желаемого изначально UPDATE, у нас будет стопицот категорий, с одним и тем же значением
size
.Внимание вопрос: "Зачем хранить одно и то же значение в 9342423 экземплярах? Как же нормализация?"
ИМХО: по крону раз в те-же сутки меняем значение ".categories_cloud {
font-size:...." в CSS файле и не усложняем зря жизнь себе и БД :)
Ну а так да, вполне себе приятное решение.
Нет, не будет, я же проверяю сначала, прежде чем публиковать. ;)
вот что получается
Никаких "9342423 экземплярах" ;)
И вот такое облако получаем:

Хм... Просто запрос:
При данных:
У меня лично выдает только одно значение - 1.2500(Как я понимаю для последнего столбца с
id
19 (MySQL5). Или я что-то недопонимаю?ИМХО все равно данные размера как таковые к категориям особого отношения не имеют, они грубо говоря связь облака тегов с категориями, да и юзаются они ведь только в нем, не так ли?
Поэтому можно было бы сделать таблицу:
Ну и в ней собственно все их(значения) хранить.
да, именно этот запрос сделает всем строкам один результат, но этот запрос только для теста, посмотри внимательно процедуру, там этот кусок кода:
вынесен в отдельную переменную @percent и все работает наура, для всех строк
Не согласен, зачем мне делать доп. таблицу, если эти данные необходимы для генерации облака (титл, урл, размер)?
Я считаю это лишним.
С тем же успехом можно было отделить "count" в другую таблицу.
count
имеет отношение к категориям,size
имеет отношение исключительно к облакам и нефиг ему делать в основной таблице.Впрочем на вкус и цвет товарищей нет. Проехали :)
Ну да я это понял, просто меня переклинило на первом запросе, стормозил признаю.
P.S.
Впринципе вполне логично, что они гененрят только одну строку ибо MAX, MIN это же агрегатные функции GROUP BY.
Можно было бы заменить аццким запросом:
Твой вариант лучше безусловно прозрачнее и быстрее, мне просто занятся нечем пока футурама скачивается.
Ну смотри, для генерации облака нам нужно помимо "размера" еще "имя жанра" и "ссылка, либо ид жанра", так?
Тогда логично чтобы они были в одной таблице, чтобы не делать лишнего жойна, так?
Тогда куда мне всунуть "размер"? Или ты мне предлагаешь одинаковые данные хранить в двух таблицах?
Скоро выложим на кинсбурге, заходи ;)
Ad1ce,
Вообще есть два способа решения без процедур, вьюх и тому подобных извращений
http://ramzes.ws/blog/cant-specify-target-table-for-update-in-from-clause
Вы про вариант с JOIN? В этой статье он тоже использовался и неудачно, возможно потому что статье 6 лет
Оставьте свой комментарий