2014-12-16 4 views
0

В сценарии телефонной системы у меня есть 2 таблицы.SQL: UPDATE из комплекса select

  • таблица1 состоит из: customer_id, call_duration, calldate, skip_billing.
  • таблица2 составлена: customer_id, bonus_seconds.

В таблице 1 хранятся все призывы для всех клиентов, а таблица2 хранит бонусные_секунды, которые представляют свободное время разговора для определенного клиента (то есть: для клиента 1 ПЕРВЫЕ 40 кумулятивных секунд бесплатны).

Мне нужно написать запрос для обновления таблицы1 в соответствии с приведенным ниже условием: установить skip_billing в пределах вызовов, которые определены бесплатно в таблице2.

Так что сначала мне нужно сгруппировать по customer_id, а затем перебрать вызовы, увеличив кумулятивную переменную (cumsec) над call_duration и соответственно установить skip_billing.

table1 пример:

|sqlid |customer_id |billsec | skipbill| 
|0  |1   |12  | 1  |<--need to set 1 due to cume=12 for customer_id=1 
|1  |1   |10  | 1  |<--need to set 1 due to cume=22 for customer_id=1 
|2  |1   |15  | 1  |<--need to set 1 due to cume=37 for customer_id=1 
|3  |1   |8  | 0  |<--nop(no operation) due to cume=45 
|4  |2   |12  | 1  |<--need to set 1 due to cume=12 for customer_id=2 
|5  |3   |12  | 1  |<--need to set 1 due to cume=12 for customer_id=3 
|6  |2   |12  | 0  |<--nop due to cume=24 for customer_id=2 
|7  |1   |12  | 0  |<--nop due to cume=49 for customer_id=1 
|8  |3   |15  | 0  |<--nop due to cumsec=27 for customer_id=3 

|customer_id |bonus_seconds| 
|1   |40   | 
|2   |20   | 
|3   |15   | 

Я попытался с запросом, как это (спасибо Гордона Линофф), который возвращает правильный набор строки:

SELECT t.cume, t.calldate, t.customer_id FROM (SELECT t.*, (@cume := @cume + billsec) AS cume FROM table1 t CROSS JOIN (SELECT @cume := 0) vars ORDER BY calldate) t, table2 sct WHERE t.cume <= sct.bonus_seconds AND t.customer_id=sct.customer_id ; 

Но когда я пытаюсь использовать жгуты UPDATE, как показано ниже, это не работает, потому что ничего не соответствует.

UPDATE table1 SET skipbill=1 WHERE sqlid=(SELECT t.sqlid FROM (SELECT t.*, (@cume := @cume + billsec) AS cume FROM table1 t CROSS JOIN (SELECT @cume := 0) vars ORDER BY calldate) t, table2 sct WHERE t.cume <= sct.bonus_seconds AND t.customer_id=sct.customer_id) ; 

Как я могу написать задачу обновления с помощью этого запроса или что-то еще лучше?

Спасибо заранее

ответ

1
UPDATE table1 
SET skipbill = 1 
WHERE sqlid IN (
    SELECT DISTINCT t.sqlid 
    FROM (
     SELECT t.*, (@cume := @cume + billsec) AS cume 
     FROM table1 t 
     CROSS JOIN (SELECT @cume := 0) vars 
     ORDER BY calldate 
    ) t, table2 sct 
    WHERE t.cume <= sct.bonus_seconds 
      AND t.customer_id = sct.customer_id 
); 
+0

спасибо! оно работает. Время выполнения запроса составляет около 13 секунд для процесса только 7k строк таблицы1, table2 - одна строка! теперь его время, чтобы уменьшить сложность :) –

+0

Попробуйте добавить отличную, если она уменьшает время выполнения ... –

+0

WHERE sqlid in (SELECT distinct t.sqlid ......... –

1

Мне кажется, что вы биллинг клиента 1 (к примеру) в течение 3 секунд, которые должны быть частью их бонус, но все равно ...

SELECT x.* 
     , SUM(y.billsec) cumu 
     , IF(SUM(y.billsec)<=z.bonus_seconds,1,0) n 
    FROM my_table x 
    JOIN my_table y 
    ON y.customer_id = x.customer_id 
    AND y.sqlid <= x.sqlid 
    LEFT 
    JOIN bonus z 
    ON z.customer_id = x.customer_id 
    GROUP 
    BY x.customer_id 
     , x.sqlid 
    ORDER 
    BY sqlid; 
+0

Вы правы! Я не нашел решение для правильного подсчета времени. вы можете сделать это :) спасибо вам в любом случае –

+0

этот вопрос занял 1 минуту 50,25 сек. очень долгое время !! но он работает –

+0

Индексирован ли customer_id (либо самостоятельно, либо как часть составного). – Strawberry