根据“技能名称”的子查询选择,以下查询相当慢。当我针对SQL执行运行一个配置文件时,我从ACDCallinformation表中获得了太多的查询,而不是针对技能名的子查询。
优化此SQL查询的最佳方法是什么?还是有一个MySQL工具来帮助检查SQL查询的成本并优化脚本?
SELECT
CASE
WHEN(
SELECT
COUNT(ag.`PKEY`) - COUNT(ag.`ANSWERTIME`)
FROM acdcallinformation ag
WHERE (ag.`COMPLETED`) = 1 AND answertime IS NULL AND DATEofcall = DATE(NOW()) AND ag.skillid = acdcallinformation.skillid
) IS NULL
THEN
0
ELSE
(
SELECT COUNT(ag.`PKEY`) - COUNT(ag.`ANSWERTIME`)
FROM acdcallinformation ag
WHERE (ag.`COMPLETED`) = 1 AND answertime IS NULL AND DATEofcall= DATE(NOW()) AND ag.skillid = acdcallinformation.skillid)
END AS 'Lost Calls',
CASE WHEN COUNT(acdcallinformation.idleonqueue) IS NULL THEN 0 ELSE COUNT(acdcallinformation.idleonqueue) END AS 'Total Calls',
CASE WHEN COUNT(acdcallinformation.`ANSWERTIME`) IS NULL THEN 0 ELSE COUNT(acdcallinformation.`ANSWERTIME`) END AS 'Answered',
(
SELECT
skillinfo.skillname
FROM skillinfo
WHERE skillinfo.pkey = acdcallinformation.skillid
) AS Skill,
SEC_TO_TIME(AVG(TIME_TO_SEC(answertime)- TIME_TO_SEC(firstringonqueue))) AS 'Average Answer Time',
SEC_TO_TIME(AVG(TIME_TO_SEC(IDLEONQUEUE) - TIME_TO_SEC(answertime))) AS 'Average Talk Time'
FROM `acdcallinformation` acdcallinformation
WHERE DATEOFCALL = DATE(NOW())
GROUP BY skill;
不确定以最佳方式显示数据:
ACDCALLINFORMATION - 当前行数3028
INSTIME PKEY DATEOFCALL CONNECTTIME FIRSTRING SKILLID
2012-07-19 14:50:16 19985 2012-07-19 14:50:16 14:50:16 5
SKILLINFO - 平均行数为5-10
INSTIME PKEY SKILLNAME
2012-07-01 13:12:01 1 Calls Outgoing
2012-07-01 13:12:01 2 Call Centre
2012-07-01 13:12:01 3 Accounts
2012-07-01 13:12:01 4 Reception
这是预期的输出:
"Lost Calls" "Total Calls" "Answered" "Skill" "Average Answer Time" "Average Talk Time"
"1" "2" "1" "Accounts" "00:00:04" "00:00:01"
"0" "5" "5" "Service" "00:00:07" "00:01:20"
答案 0 :(得分:3)
试试这个,使用内部联接来提高性能并避免不必要的subquerys
SELECT
COALESCE(ag.skillcount, 0) AS 'Lost Calls',
CASE WHEN COUNT(acdcallinformation.idleonqueue) IS NULL THEN 0 ELSE COUNT(acdcallinformation.idleonqueue) END AS 'Total Calls',
CASE WHEN COUNT(acdcallinformation.`ANSWERTIME`) IS NULL THEN 0 ELSE COUNT(acdcallinformation.`ANSWERTIME`) END AS 'Answered',
si.skillname AS Skill,
SEC_TO_TIME(AVG(TIME_TO_SEC(answertime)- TIME_TO_SEC(firstringonqueue))) AS 'Average Answer Time',
SEC_TO_TIME(AVG(TIME_TO_SEC(IDLEONQUEUE) - TIME_TO_SEC(answertime))) AS 'Average Talk Time'
FROM `acdcallinformation` acdcallinformation
LEFT JOIN (
SELECT skillid, COUNT(`PKEY`) - COUNT(`ANSWERTIME`) skillcount
FROM acdcallinformation
WHERE (`COMPLETED`) = 1 AND answertime IS NULL AND DATEofcall = DATE(NOW())
) ag ON AND ag.skillid = acdcallinformation.skillid
LEFT JOIN skillinfo si ON si.pkey = acdcallinformation.skillid
WHERE DATEOFCALL = DATE(NOW())
GROUP BY si.skillname;
答案 1 :(得分:2)
您似乎正在尝试确保将NULL
转换为0
s。因此:
SELECT
IFNULL(
(SELECT COUNT(ag.`PKEY`) - COUNT(ag.`ANSWERTIME`) FROM acdcallinformation ag
WHERE (ag.`COMPLETED`) = 1 AND answertime IS NULL
AND DATEofcall = DATE(NOW()) AND ag.skillid = acdcallinformation.skillid
), 0) AS 'Lost Calls',
IFNULL(COUNT(acdcallinformation.idleonqueue), 0) AS 'Total Calls',
IFNULL(COUNT(acdcallinformation.`ANSWERTIME`),0) AS 'Answered',
(
SELECT
skillinfo.skillname
FROM skillinfo
WHERE skillinfo.pkey = acdcallinformation.skillid
) AS Skill,
SEC_TO_TIME(AVG(TIME_TO_SEC(answertime)- TIME_TO_SEC(firstringonqueue))) AS 'Average Answer Time',
SEC_TO_TIME(AVG(TIME_TO_SEC(IDLEONQUEUE) - TIME_TO_SEC(answertime))) AS 'Average Talk Time'
FROM `acdcallinformation` acdcallinformation
WHERE DATEOFCALL = DATE(NOW())
GROUP BY skill;
尽管如此,使用消耗此数据的语言将这些NULL
转换为零可能更容易......只是一个想法。
此外,我阅读COUNT
的文档让我觉得它永远不会返回NULL
,因此:
SELECT
(SELECT COUNT(ag.`PKEY`) - COUNT(ag.`ANSWERTIME`) FROM acdcallinformation ag
WHERE (ag.`COMPLETED`) = 1 AND answertime IS NULL
AND DATEofcall = DATE(NOW()) AND ag.skillid = acdcallinformation.skillid
) AS 'Lost Calls',
COUNT(acdcallinformation.idleonqueue) AS 'Total Calls',
COUNT(acdcallinformation.`ANSWERTIME`) AS 'Answered',
(
SELECT
skillinfo.skillname
FROM skillinfo
WHERE skillinfo.pkey = acdcallinformation.skillid
) AS Skill,
SEC_TO_TIME(AVG(TIME_TO_SEC(answertime)- TIME_TO_SEC(firstringonqueue))) AS 'Average Answer Time',
SEC_TO_TIME(AVG(TIME_TO_SEC(IDLEONQUEUE) - TIME_TO_SEC(answertime))) AS 'Average Talk Time'
FROM `acdcallinformation` acdcallinformation
WHERE DATEOFCALL = DATE(NOW())
GROUP BY skill;
最后,我认为您可以使用JOIN
SELECT
IFNULL(
(SELECT COUNT(ag.`PKEY`) - COUNT(ag.`ANSWERTIME`) FROM acdcallinformation ag
WHERE (ag.`COMPLETED`) = 1 AND answertime IS NULL
AND DATEofcall = DATE(NOW()) AND ag.skillid = acdcallinformation.skillid
), 0) AS 'Lost Calls',
IFNULL(COUNT(acdcallinformation.idleonqueue), 0) AS 'Total Calls',
IFNULL(COUNT(acdcallinformation.`ANSWERTIME`),0) AS 'Answered',
skillinfo.skillname AS Skill,
SEC_TO_TIME(AVG(TIME_TO_SEC(answertime)- TIME_TO_SEC(firstringonqueue))) AS 'Average Answer Time',
SEC_TO_TIME(AVG(TIME_TO_SEC(IDLEONQUEUE) - TIME_TO_SEC(answertime))) AS 'Average Talk Time'
FROM `acdcallinformation` acdcallinformation
INNER JOIN skillinfo ON skillinfo.pkey = acdcallinformation.skillid
WHERE DATEOFCALL = DATE(NOW())
GROUP BY skill;
答案 2 :(得分:2)
尝试此查询。整个查询只是一个猜测,但如果您提供了一些数据,那将是更好的。我也使用id作为主键,你需要用自己的密钥替换它。避免使用子查询而是使用连接它们更快。这是查询。
SELECT
IF(l.LDifference IS NULL,0,r.RDifference) AS 'Lost Calls',
IF(COUNT(acdcallinformation.idleonqueue) IS NULL , 0 , COUNT(acdcallinformation.idleonqueue))AS 'Total Calls',
IF(COUNT(acdcallinformation.`ANSWERTIME`) IS NULL,0,COUNT(acdcallinformation.`ANSWERTIME`))AS 'Answered',
(SELECT skillinfo.skillname FROM skillinfo WHERE skillinfo.pkey = acdcallinformation.skillid) AS Skill,
SEC_TO_TIME(AVG(TIME_TO_SEC(a.answertime)- TIME_TO_SEC(a.firstringonqueue))) AS 'Average Answer Time',
SEC_TO_TIME(AVG(TIME_TO_SEC(a.IDLEONQUEUE) - TIME_TO_SEC(a.answertime))) AS 'Average Talk Time'
FROM acdcallinformation as a
INNER JOIN(
SELECT
(COUNT(ag.`PKEY`) - COUNT(ag.`ANSWERTIME`)) as `LDifference`
FROM acdcallinformation ag
WHERE (ag.`COMPLETED`) = 1 AND answertime IS NULL AND DATEofcall = DATE(NOW()) AND ag.skillid = acdcallinformation.skillid
) as l ON l.id = a.id
INNER JOIN(
SELECT (COUNT(ag.`PKEY`) - COUNT(ag.`ANSWERTIME`)) as `RDifference`
FROM acdcallinformation ag
WHERE (ag.`COMPLETED`) = 1 AND answertime IS NULL AND DATEofcall= DATE(NOW()) AND ag.skillid = acdcallinformation.skillid
) as r ON r.id = a.id
WHERE a.DATEOFCALL = DATE(NOW())
GROUP BY skill;
答案 3 :(得分:2)
试试这个。 使用INNER JOIN,IF()并尝试避免不必要的子查询。
SELECT IFNULL(ag.skillcount, 0) AS 'Lost Calls', COUNT(info.idleonqueue) AS 'Total Calls',
COUNT(info.ANSWERTIME) AS 'Answered', si.skillname AS Skill,
SEC_TO_TIME(AVG(TIME_TO_SEC(answertime)- TIME_TO_SEC(firstringonqueue))) AS 'Average Answer Time',
SEC_TO_TIME(AVG(TIME_TO_SEC(IDLEONQUEUE) - TIME_TO_SEC(answertime))) AS 'Average Talk Time'
FROM acdcallinformation AS info
INNER JOIN (
SELECT skillid, COUNT(PKEY)-COUNT(ANSWERTIME) skillcount
FROM acdcallinformation
WHERE COMPLETED = 1 AND DATEofcall = DATE(NOW()) AND answertime IS NULL
) ag ON ag.skillid = info.skillid
INNER JOIN skillinfo si ON si.pkey = info.skillid
WHERE DATEOFCALL = DATE(NOW())
GROUP BY si.skillname;