У меня есть таблица в Postgres с SIP-логом.
| in | out | sec |
| 112 | sip/113-random | 12 |
| 113 | sip/112-random | 45 |
| 112 | sip/114-random | 40 |
| 113 | sip/114-random | 35 |
| 117 | sip/113-random | 11 |
| 117 | sip/113-random | 25 |
| 115 | sip/112-random | 98 |
| 115 | sip/117-random | 78 |
| 112 | sip/113-random | 18 |
Мне нужно сложить все sec
в «in» и «out» с одним SIP и группировать по номеру SIP.
Пример:
....
112 - 54
113 - 152
115 - 25
....
Теперь я использую этот код. Но это работает в цикле и занимает очень много времени.
$array_sip=array(110,111 .... 199);
foreach ($array_sip as $sip) {
$sum_out=0;
$sum_in=0;
$sql = "SELECT SUM(sec) AS sec
FROM public.cdr
WHERE calldate::text like '".$date."%'
AND disposition='ANSWERED'
AND out like 'SIP/".$sip."%'
AND sec > 15
";
foreach ($db->query($sql) as $row) {
$sum_out=$row['sec'];
}
$sql = "SELECT SUM(sec) AS sec
FROM public.cdr
WHERE calldate::text like '".$date."%'
AND disposition='ANSWERED'
AND in = '".$sip."'
AND sec > 3";
foreach ($db->query($sql) as $row) {
$sum_in=$row['sec'];
}
$sum=round((($sum_out+$sum_in)/60),1);
$loading_level.= $sip.' - '.$sum;
}
Как я могу оптимизировать запрос?
Вы должны составить и выполнить запрос следующим образом:
SELECT substring(out FROM '\d+'),
SUM(sec) AS sec
FROM public.cdr
WHERE calldate::text LIKE '<your date>%'
AND disposition = 'ANSWERED'
AND out LIKE ANY ('SIP/<sip1>-%', 'SIP/<sip2>-%', ...)
AND sec > 15
GROUP BY substring(out FROM '\d+');
Вам придется заменить <...>
в выше с вашими фактическими значениями.
LIKE ANY
условие пройдет все, что соответствует одному из шаблонов.
Таким образом, вы можете получить все это в одном запросе, который будет более эффективным.
Индексы на calldate::text
а также out
может ускорить обработку.
Других решений пока нет …