Я хотел бы знать, как я могу оптимизировать sql-запрос.
Структура таблицы выглядит следующим образом:
Комиссии:
+---------------------------+----------------------------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------------+----------------------------------------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| network_commission | int(11) | YES | | NULL | |
+---------------------------+----------------------------------------------+------+-----+---------+----------------+
РекламодательBalanceTransactions:
+---------------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+---------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| commission_id | int(11) | YES | MUL | NULL | |
| transaction_type | varchar(255) | YES | | NULL | |
| amount | decimal(10,2) | YES | | 0.00 | |
| currency_code | varchar(3) | YES | | NULL | |
| created_at | datetime | NO | | NULL | |
| updated_at | datetime | NO | | NULL | |
+---------------------+---------------+------+-----+---------+----------------+
Правила:
РекламодательBalanceTransactions может иметь только 2 типа: "new_commissions" или "nt_commission". Тип "new_commissions" появляется только один раз, пока "nt_commission" может появиться n раз (по крайней мере один раз максимум бесконечно с разными значениями).
Обновление столбца network_commission таблицы комиссий:
network_commission начинается со значения NULL и должно быть заполнено следующим выражением: значением (количеством) первого созданного рекламодателяBalanceTransaction типа 'nt_commission' * 100/значением (количеством) рекламодателяBalanceTransaction типа 'new_commission'.
Следующий запрос выполняет следующее:
update commissions set commissions.network_commission=(
select t.amount * 100 / new_com_tran.amount
from advertiser_balance_transactions new_com_tran,
(select nt_com_tran.amount, nt_com_tran.commission_id
from advertiser_balance_transactions nt_com_tran
where nt_com_tran.transaction_type = 'nt_commission'
order by created_at asc limit 1) t
where commissions.id=new_com_tran.commission_id
AND new_com_tran.transaction_type = 'new_commissions'
AND t.commission_id=commissions.id)
where commissions.amount != 0;
Пример данных:
комиссии:
+--------+--------------------+
| id | network_commission |
+--------+--------------------+
| 887755 | NULL |
| 887752 | NULL |
| 887751 | NULL |
| 887750 | NULL |
| 887749 | NULL |
| 887748 | NULL |
| 887747 | NULL |
| 887746 | NULL |
| 887745 | NULL |
| 887744 | NULL |
+--------+--------------------+
AdvertiserBalanceTransactions:
+---------+---------------+------------------+--------+---------------+---------------------+---------------------+
| id | commission_id | transaction_type | amount | currency_code | created_at | updated_at |
+---------+---------------+------------------+--------+---------------+---------------------+---------------------+
| 1432047 | 887744 | new_commissions | -0.30 | RON | 2018-01-22 09:09:54 | 2018-01-22 09:09:54 |
| 1432048 | 887744 | nt_commission | -0.12 | RON | 2018-01-22 09:09:54 | 2018-01-22 09:09:54 |
| 1432048 | 887744 | nt_commission | -0.23 | RON | 2018-01-22 09:10:54 | 2018-01-22 09:10:54 |
| 1432049 | 887745 | new_commissions | -0.30 | RON | 2018-01-22 09:09:57 | 2018-01-22 09:09:57 |
| 1432050 | 887745 | nt_commission | -0.12 | RON | 2018-01-22 09:09:57 | 2018-01-22 09:09:57 |
| 1432051 | 887746 | new_commissions | -0.30 | RON | 2018-01-22 11:06:23 | 2018-01-22 11:06:23 |
| 1432052 | 887746 | nt_commission | -0.12 | RON | 2018-01-22 11:06:23 | 2018-01-22 11:06:23 |
| 1432053 | 887747 | new_commissions | -0.30 | RON | 2018-01-22 11:09:35 | 2018-01-22 11:09:35 |
| 1432054 | 887747 | nt_commission | -0.12 | RON | 2018-01-22 11:09:35 | 2018-01-22 11:09:35 |
| 1432055 | 887748 | new_commissions | -0.30 | RON | 2018-01-22 11:11:09 | 2018-01-22 11:11:09 |
| 1432056 | 887748 | nt_commission | -0.12 | RON | 2018-01-22 11:11:09 | 2018-01-22 11:11:09 |
| 1432057 | 887749 | new_commissions | -0.30 | RON | 2018-01-22 11:19:10 | 2018-01-22 11:19:10 |
| 1432058 | 887749 | nt_commission | -0.12 | RON | 2018-01-22 11:19:10 | 2018-01-22 11:19:10 |
| 1432059 | 887750 | new_commissions | -0.30 | RON | 2018-01-22 11:22:21 | 2018-01-22 11:22:21 |
| 1432060 | 887750 | nt_commission | -0.12 | RON | 2018-01-22 11:22:21 | 2018-01-22 11:22:21 |
| 1432061 | 887751 | new_commissions | -0.30 | RON | 2018-01-23 10:29:48 | 2018-01-23 10:29:48 |
| 1432062 | 887751 | nt_commission | -0.12 | RON | 2018-01-23 10:29:48 | 2018-01-23 10:29:48 |
| 1432063 | 887752 | new_commissions | -0.30 | RON | 2018-01-23 12:55:11 | 2018-01-23 12:55:11 |
| 1432064 | 887752 | nt_commission | -0.12 | RON | 2018-01-23 12:55:11 | 2018-01-23 12:55:11 |
| 1432069 | 887755 | new_commissions | -2.10 | RON | 2018-02-22 11:38:45 | 2018-02-22 11:38:45 |
| 1432070 | 887755 | nt_commission | -0.84 | RON | 2018-02-22 11:38:45 | 2018-02-22 11:38:45 |
+---------+---------------+------------------+--------+---------------+---------------------+---------------------+
Есть ли способ оптимизировать этот запрос обновления?
Я бы предложил использовать JOINS
update commissions c
LEFT JOIN advertiser_balance_transactions new_t
ON c.id=new_t.commission_id AND new_t.transaction_type='new_commissions'
LEFT JOIN advertiser_balance_transactions first_nt_t
ON c.id=first_nt_t.commission_id AND first_nt_t.transaction_type='nt_commission'
AND first_nt_t.created_at=(SELECT MIN(created_at)
FROM advertiser_balance_transactions t3
WHERE t3.commission_id=c.id AND transaction_type='nt_commission')
set commissions.network_commission = first_nt_t.amount * 100 / new_t.amount
Вы можете ПРИСОЕДИНЯТЬ два выбора в одном и в зависимости от вашей СУБД, даже если выбор полностью исключается, поскольку некоторые (например, SYBASE) позволяют использовать несколько таблиц в FROM.