我有以下字段和索引的表:
我需要进行一个查询:
检查表,如果有拨号事件,之后(使用相同的话) unique_id)没有 Bridge 或 Hangup 事件
或
如果有 NewCallerId 事件,其后没有挂断事件(具有相同的unique_id)或没有拨打事件(call_id = current) UNIQUE_ID)
有一个查询,但我没有让它工作,用户的答案也没有帮助。 这是在395秒(太长时间)内完成工作的查询:
SELECT t1.*
FROM ASTERISK t1
WHERE EXISTS (SELECT t2.*
FROM ASTERISK t2
WHERE t1.OPERATOR_DIAL = '$extension'
AND t1.EVENT = 'Dial'
AND NOT EXISTS (SELECT t3.*
FROM ASTERISK t3
WHERE t3.UNIQUE_ID = t1.UNIQUE_ID
AND ( t3.EVENT = 'Hangup'
OR t3.EVENT = 'Bridge' )))
OR EXISTS (SELECT t4.*
FROM ASTERISK t4
WHERE t1.EVENT = 'NewCallerid'
AND t1.OPERATOR_DIAL = '$extension'
AND NOT EXISTS (SELECT t5.*
FROM ASTERISK t5
WHERE ( t5.UNIQUE_ID = t1.UNIQUE_ID
AND t5.EVENT = 'Hangup' )
OR ( t5.CALL_ID = t1.UNIQUE_ID
AND t5.EVENT = 'Dial' )))
ORDER BY DATE DESC
LIMIT 1
试图用JOINS重写它,但是获取#1248 - 每个派生表必须有自己的别名
这是我尝试使用JOIN查询:
SELECT t1.*
FROM asterisk t1
INNER JOIN (SELECT t2.* FROM asterisk t2
WHERE
t1.operator_dial = '$extension'
AND t1.event = 'Dial'
LEFT OUTER JOIN (SELECT t3.* FROM asterisk t3
WHERE t3.unique_id = t1.unique_id AND (t3.event = 'Hangup' OR t3.event = 'Bridge')))
OUTER JOIN (SELECT t4.* FROM asterisk t4
WHERE t1.event = 'NewCallerid'
AND t1.operator_dial = '$extension'
LEFT OUTER JOIN (SELECT t5.* FROM asterisk t5
WHERE (t5.unique_id = t1.unique_id AND t5.event = 'Hangup') OR (t5.call_id = t1.unique_id AND t5.event = 'Dial')))
ORDER BY DATE DESC
LIMIT 1
要显示查询应该如何工作我制作了2个屏幕截图(顶部部分有一些调用不在查询结果中,而底部部分是一个调用必须在查询结果中:
答案 0 :(得分:1)
我刚开始在堆栈交换上发帖。在没有深入潜水的情况下,我注意到t2和t4的内部连接没有与t1中的任何值匹配的值(可能是原始查询如此长的原因)。
旧查询已删除.......
感谢屏幕截图,这有帮助。那么你希望你的查询返回的是活动调用(没有'hang-ups'或'Bridges'的调用)然后你想要没有相关拨号事件的NewcallerID事件和最后用桥接器拨打事件但是他们之后没有桥梁
SELECT *
FROM Asterisk t1
WHERE t1.unique_id not in
(Select unique_id
from Asterisk t2
Where event = 'Hangup', 'Bridge')
UNION
select *
from asterisk t3
Where event = 'NewCallerID'
and t3.unique_id not in
(Select unique_id
from Asterisk t4
Where event = 'Dial')
UNION
Select distinct *
from asterisk t5
inner join asterisk t6
on t5.unique_ID = t6.Unique_id
and t6.event = 'Dial'
Where t5.event = 'Bridge'
and t6.id > t5.id
我想我已经涵盖了所有案例。 (但闻起来有点hackish)。 编辑:在未覆盖拨号之前存在桥的事件
答案 1 :(得分:1)
我认为你过度复杂了。通过t2别名存在而没有连接 在唯一ID上,您将获得笛卡尔结果。
我内联评论了这个查询,所以一定要在运行之前把它们拿出去。
SELECT
t1.*
FROM
ASTERISK t1
LEFT JOIN ASTERISK t2
ON t1.Unique_ID = t2.Unique_ID
AND ( t2.Event = 'Hangup'
OR t2.Event = 'Bridge' )
LEFT JOIN ASTERISK t3
ON t1.unique_id = t3.unique_id
AND t3.EVENT = 'Hangup'
LEFT JOIN ASTERISK t4
ON t1.unique_id = t4.call_id
AND t4.EVENT = 'Dial'
WHERE
-- THESE ARE THE PRIMARY CONDITIONS YOU WANT...
-- a specific operator extension and looking for
-- either a dial or newcallerid
t1.OPERATOR_DIAL = '$extension'
AND ( t1.EVENT = 'Dial'
OR t1.EVENT = 'NewCallerID' )
AND (
-- if an outgoing DIAL, you are concerned with
-- alias t2 and NOT having any hangup or bridge
( t1.EVENT = 'Dial'
AND t2.Unique_ID IS NULL )
OR
-- its from the NewCallerID record via t1 alias
-- and you do not want hangup or dial based on
-- the unique ID vs Call ID respectively to the
-- t3 and t4 aliases
( t1.EVENT = 'NewCallerID'
AND t3.Unique_ID IS NULL
AND t4.Unique_ID IS NULL )
)
ORDER BY
t1.`DATE` DESC
LIMIT 1
REVISION基于样本数据,但NewCallerID样本数据除外......
这应该极其简化你所拥有的 - 至少对于出站呼叫。没有显示“NewCallerID”的数据,因此如果没有更好的样本数据,我无法应用该答案。
无论如何,我更改为预先查询给定运营商扩展的所有调用,并根据每个调用的唯一ID分组的呼叫数据记录中的明显自动增量ID列创建第一个和最后一个事件。从那以后,它直接连接到每个表,这样我们就可以看到调用是如何开始的以及它的最后一个活动。从那里,它是一个简单的where子句,最后一个事件仍处于“newstate”设置。如果还有其他设置,例如暂停,电话会议,等等,则需要将其调整为NOT(挂断或桥接)状态......
SELECT
PerCallSummary.*,
StartCall.event as BeginEvent,
StartCall.id as BeginEventID,
LastCall.event as EndEvent,
LastCall.id as EndEventID
from
( SELECT
t1.unique_id,
t1.id beginCall,
MAX(t2.id) as lastActivity
from
asterisk t1
join asterisk t2
on t1.unique_id = t2.unique_id
where
t1.operator_dial = '$extension'
and t1.event = 'Dial'
group by
t1.unique_id,
t1.id ) as PerCallSummary
JOIN Asterisk as StartCall
ON PerCallSummary.beginCall = StartCall.id
JOIN Asterisk as LastCall
ON PerCallSummary.lastActivity = LastCall.id
where
LastCall.Event = 'Newstate'
调整内部“PerCallSummary”查询
我认为这会解决这个问题......你没有得到结果的原因是我错误地将你的数据解释为只是简要介绍它的内容,因为operator_dial值没有转发到每条记录。因此,现在调整内部查询以加入星号AGAIN,但仅限于呼叫的unique_id(因为操作员拨号会失败,否则他们没有被填写)。因此,调用将始终与第一个t1记录BEGIN,所以我只是将其作为基础,但现在只有t2记录ID的MAX()...现在,您应该得到正确的结果以继续此操作。 / p>
无论如何,获取一些“NewCallerID”看起来像的示例数据,我们可以调整它以包含它和它的结束标准。