3

以下のクエリは、「スキル名」のサブクエリの選択に関してはかなり遅いです。SQL実行に対してプロファイルを実行すると、skillnameのサブクエリに対してACDCallinformationテーブルから1行あたりのクエリが多すぎます。

このSQLクエリを最適化する最良の方法は何ですか?またはSQLクエリのコストをチェックしてスクリプトを最適化するのに役立つMySQLツールはありますか?

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"
4

4 に答える 4

3

これを試してください。内部結合を使用してパフォーマンスを向上させ、不要なサブクエリを回避しています

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;   
于 2013-02-07T16:41:48.920 に答える
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;
于 2013-02-07T16:36:21.920 に答える
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;
于 2013-02-07T17:58:29.353 に答える
2

NULLs が s に確実に変換されるようにしようとしているようです0。したがって:

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ただし、このデータを消費する言語を使用してこれらの s をゼロに変換する方が簡単かもしれません...ただの考えです。

また、 のドキュメントを読むと、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;

最後に、2番目のクエリを次のように処理できると思います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;
于 2013-02-07T16:35:29.740 に答える