У меня есть сайт электронной коммерции, где клиенты регистрируются и видят цены на различные продукты. У каждого клиента есть свой прейскурант, и цены могут быть установлены несколькими способами (источниками). Таблица ниже:
CREATE TABLE customer_price_list (
customer_price_id int(11) NOT NULL AUTO_INCREMENT,
customer_account_id int(11) NOT NULL,
product_id int(11) DEFAULT NULL,
currency_id int(11) DEFAULT NULL,
customer_price decimal(7,2) DEFAULT NULL,
source enum('TRADE_DEFAULT','TEMPLATE','SAGE','MANUAL') DEFAULT NULL,
PRIMARY KEY (customer_price_id),
KEY customer_account_id (customer_account_id),
KEY product_id (product_id),
KEY currency_id (currency_id),
KEY source (source)
)
Принимая только product_id, customer_price и source, образцы данных для одного клиента могут выглядеть (с использованием строки для product_id для иллюстрации):
Prod_1, 10.00, TRADE_DEFAULT
Prod_2, 20.00, TRADE_DEFAULT
Prod_3, 25.00, MANUAL
И другой клиент:
Prod_1, 7.50, SAGE
Prod_2, 20.00, TRADE_DEFAULT
Prod_3, 30.00, TRADE_DEFAULT
Базовая цена за что-то без скидки - это когда TRADE_DEFAULT - это выше показывает, что эти два клиента имели цену TRADE_DEFAULT для двух предметов, но получили скидку на один предмет.
Цены TRADE_DEFAULT устанавливаются путем импорта CSV файла с файлами product_id, currency_id и customer_price. В PHP я просматриваю все строки в CSV и привязываю значения к этому запросу:
insert into customer_price_list
(customer_price_id, customer_account_id, product_id, currency_id, customer_price, source)
select 0, customer_account_id, :product_id, :currency_id, :price, 'TRADE_DEFAULT' from customer_account
Это отлично работает, когда client_price_list пуст (для всех комбинаций product_id/currency_id в CSV). Но если некоторые клиенты уже имеют записи product_id/currency_id, это приведет к появлению дополнительных строк (т.е. Для продукта для этого клиента будет две или более цен)
Итак, при обработке CSV я хочу:
A) обновить любое существующее TRADE_DEFAULT до нового значения из CSV (снова запустить из цикла содержимого CSV)
update customer_price_list set customer_price = :price
where currency_id=:currency_id and product_id=:product_id and source ='TRADE_DEFAULT'
B) введите цену TRADE_DEFAULT, если у этого клиента нет цены за этот товар/валюту
insert (ONLY IF NO PRICE OF ANY SOURCE IS THERE) into customer_price_list
(customer_price_id, customer_account_id, product_id, currency_id, customer_price, source)
select 0, customer_account_id, :product_id, :currency_id, :price, 'TRADE_DEFAULT' from customer_account
Здесь мне нужна помощь. Я искал условные запросы вставки, но я могу найти только, где они вставляют один повторный вызов следующим образом:
insert into table1 (user,rating,last_modified)
select 'user1', 1999, NOW() from table1
where not exists (
select * from table1
where last_modified > '2007-04-13 08:52:41'
and user='user1'
) limit 1
Но я хочу сделать вставку. Выберите и сделайте вставку, если необходимо, для всех клиентов.
Благодарю.
Используя предложение @Stavr00, я придумал следующее:
Сначала добавьте индекс по трем столбцам, чтобы сделать продукт/валюту уникальной для каждого клиента:
alter table customer_price_list add UNIQUE INDEX unq_cust_prod (customer_account_id ASC, product_id ASC, currency_id ASC)
Затем измените запрос:
insert into customer_price_list
(customer_price_id, customer_account_id, product_id, currency_id, customer_price, source)
select 0, customer_account_id, :product_id, :currency_id, :price, 'TRADE_DEFAULT' from customer_account
ON DUPLICATE KEY UPDATE customer_price=customer_price;
Сделав обновление, устанавливающее цену на текущее значение, запрос становится только условной вставкой. В сочетании с запросом обновления на шаге A в моем вопросе он делает то, что я хочу.
Наверное, я мог бы использовать UPDATE ON DUPLICATE KEY UPDATE, чтобы выполнить работу другого запроса и сделать все это на одном. Но я бы хотел только обновить существующие записи источника = TRADE_DEFAULT, поэтому не знаю, как это сделать.
Кроме того, похоже, я мог использовать вставку ignore, но поскольку это не означало бы некоторые реальные ошибки, такие как несоответствие типов, я думал, что мое решение было безопаснее.
Комментарии приветствуются!
Попробуйте использовать слияние:
https://docs.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql
Это может быть полезно в вашем случае, так как позволяет вставлять значения на основе условия и обновления, если они уже существуют.
ON DUPLICATE KEY UPDATE
для оператора вставки.