Вложенное обновление mySQL с использованием COUNT / MIN / MAX из другой таблицы - PullRequest
2 голосов
/ 27 сентября 2011

У меня есть две большие таблицы: products (500k записей) и store_products (> 3 мм записей). Products является основным, а product_stores - это отдельные местоположения с продуктом.

Мне нужно запустить один запрос QUERY, суммирующий информацию из product_stores, и обновить соответствующий продукт.

Когда этот набор данных был меньшего размера, мы делали это с помощью вложенного запроса:

SELECT productid,COUNT(id) as count,MIN(price) as lowprice,MAX(price) as highprice FROM store_products
WHILE (productid){ update product set stores = count, min = lowprice, max = highprice WHERE productid = $productid }
GROUP BY productid

Я довольно новичок во вложенных обновлениях и не знаю, как установить несколько полей с помощью объединения и группировки.

Структура [усечена до соответствующих полей]:

CREATE TABLE product ( 
product_id INT UNSIGNED NOT NULL AUTO_INCREMENT,     
stores INT UNSIGNED NOT NULL DEFAULT '0',    
lowprice DECIMAL (6,2) NOT NULL DEFAULT '000.00', 
highprice  DECIMAL (6,2) NOT NULL DEFAULT '000.00', 
PRIMARY KEY (product_id), 
KEY stores (stores) 
)

CREATE TABLE store_product (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,    
product_id INT UNSIGNED NOT NULL,
price DECIMAL(7,2) NOT NULL DEFAULT '0.00',
PRIMARY KEY (storeproduct_id),
KEY product_id (product_id)
);

Поля для обновления:

  • store [количество записей store_product по productid]
  • минимальная цена [MIN цены по продукту]
  • максимальная цена [МАКС. Цена по продукту]

1 Ответ

4 голосов
/ 27 сентября 2011

Выполнение одного запроса для обновления таблиц такого размера, вероятно, займет некоторое время. В любом случае - следующее должно дать вам то, что вам нужно. Хитрость заключается в том, чтобы создать псевдоним таблицы продуктов, а затем сослаться на таблицу продуктов в подвыборке, используя этот псевдоним. Итак:

update product p 
set p.lowprice = (select min(price) from store_product sp where sp.product_id = p.product_id),
    p.highprice = (select max(price) from store_product sp where sp.product_id = p.product_id),
    p.stores = (select count(*) from store_product sp where sp.product_id = p.product_id)
where product_id in (select sp.product_id from store_product sp);

Одна хитрость здесь заключается в том, что столбец store не будет обновляться до 0 для строк, которых нет в таблице store_product. Чтобы удовлетворить это, вы можете использовать IFNULL при выполнении глобального обновления:

update product p
set lowprice = ifnull((select min(price) from store_product sp where sp.product_id = p.product_id),0),
    highprice = ifnull((select max(price) from store_product sp where sp.product_id = p.product_id),0),
    stores = ifnull((select count(*) from store_product sp where sp.product_id = p.product_id),0);

Вы можете попробовать оба варианта и посмотреть, что быстрее.

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...