Можно ли выбрать несколько перекрывающихся диапазонов дат одним запросом, используя mysql? - PullRequest
0 голосов
/ 01 февраля 2012

В настоящее время у меня есть несколько большой оператор SQL, который СОЕДИНЯЕТ один и тот же оператор SELECT 3 раза каждый раз с большим диапазоном дат. IE последние 30 дней, последние 90 дней и последние 180 дней. SQL работает просто отлично, и я даже согласен с тем фактом, что выполнение запроса занимает много времени, мне просто интересно, есть ли возможность сделать то же самое с помощью только одного оператора SELECT.

Видя, как пару человек попросили посмотреть мой код: -

SELECT mdt_userid AS logging_officer,
    'Last 30 Days' AS timespan,
    ACD_Time,
    TRUNCATE (( 1 - ( (TotalAssisting+TotalBRB+TotalShift+TotalLunch+TotalBreak-IF(TotalLunch<(DaysLoggedIn*Lunch),TotalLunch,(DaysLoggedIn*Lunch))-IF((TotalBRB+TotalBreak)<(DaysLoggedIn*1800),(TotalBRB+TotalBreak),(DaysLoggedIn*1800))) / (TotalLoginTime-TotalEreq-TotalDefault) ) ) *100,2) AS Utilization_percent,
    TRUNCATE((GRS_total/calls)*100,1) AS Ratio,
    IF (TotalACW =0,0,TotalACW / calls) AS ACW,
    grs.percent AS percent,
    TRUNCATE (((grs_total - wo_ci) / grs_total) *100,2) AS percent_w_ci,
    TRUNCATE (calls / ( ((TotalLoginTime-TotalEreq-TotalDefault) /3600) / 8.75 ) ,2) AS call_per_hour,
    TRUNCATE (GRS_total / ( ((TotalLoginTime-TotalEreq-TotalDefault) /3600) / 8.75 ) ,2) AS grs_per_hour 
FROM (SELECT DISTINCT fullname,
            SUM( IF (ReasonCode =  '138',  `ReasonCodeDuration` , 0) ) AS TotalAssisting,
            SUM( IF (ReasonCode =  '146',  `ReasonCodeDuration` , 0) ) AS TotalBRB,
            SUM( IF (ReasonCode =  '143',  `ReasonCodeDuration` , 0) ) AS TotalShift,
            SUM( IF (ReasonCode =  '141',  `ReasonCodeDuration` , 0) ) AS TotalACW,
            SUM( IF (ReasonCode =  '231',  `ReasonCodeDuration` , 0) ) AS TotalEreq,
            SUM( IF (ReasonCode =  '0',  `ReasonCodeDuration` , 0) ) AS TotalDefault,
            COUNT(ReasonCode = '136') AS CountLunch,
            SUM( IF (ReasonCode =  '136',  `ReasonCodeDuration` , 0) ) AS TotalLunch,
            SUM( IF (ReasonCode =  '137',  `ReasonCodeDuration` , 0) ) AS TotalBreak,
            SUM(  `ReasonCodeDuration` ) AS NRduration
        FROM  `CiscoAgentNotready` 
        WHERE StartDate >= '".adjustdate($DateTo,0,0,-30)." 00:00:00' 
                AND StartDate <= '".$DateTo." 23:59:59'
        GROUP BY fullname)
        AS notready, 
    (SELECT DISTINCT agentname,
            SUM( loginduration ) AS TotalLoginTime, COUNT(Date(logondate)) as DaysLoggedIn
        FROM CiscoAgentLogintime
        WHERE logondate  >= '".adjustdate($DateTo,0,0,-30)." 00:00:00' 
                AND logondate  <= '".$DateTo." 23:59:59'
        GROUP BY agentname)
        AS logintime, 
    (SELECT DISTINCT full_name, 
            SUM( handled ) AS calls
        FROM  `CiscoAgentCalls` 
        WHERE DateCol   >= '".adjustdate($DateTo,0,0,-30)."'  
                AND DateCol   <= '".$DateTo."'
        GROUP BY full_name)
        AS calls, 
    (SELECT DISTINCT logging_officer, 
            SUM( first_call ) AS firstcall, 
            SUM(IF (Config_item =  'unknown', 1, 0) ) AS wo_ci,
            COUNT( * ) AS GRS_total, 
            TRUNCATE ((SUM( first_call ) / COUNT( * )) *100,2) AS percent
        FROM (SELECT logging_officer, 
                IF (logging_officer =  `Resolving_Officer` , 1, 0) AS first_call, 
                Config_item
            FROM  `callcentergrsdata` 
            WHERE log_Date >= '".adjustdate($DateTo,0,0,-30)." 00:00:00' 
                 AND log_Date <= '".$DateTo." 23:59:59') 
            AS a
        GROUP BY logging_officer) 
        AS grs,
    (SELECT DISTINCT agtName,
            SUM(TalkTime) as sumTalk,
            SUM(CallsHandled) as answered,
            SUM(TalkTime)/SUM(CallsHandled) as ACD_Time
        FROM (SELECT CONCAT( LastName,  ', ', FirstName ) AS agtName,
                TalkTime, 
                CallsHandled
            FROM `CiscoAgentAHT`
            WHERE DateCol   >= '".adjustdate($DateTo,0,0,-30)."'  
                AND DateCol   <= '".$DateTo."') as subAHT
        GROUP BY agtName) 
        AS AHT,
    techjtblnew
WHERE mdt_userid = '".$user."'
AND notready.fullname = logintime.agentname
AND calls.full_name = notready.fullname 
AND calls.full_name = AHT.agtName
AND techjtblnew.cisco = notready.fullname 
AND grs.logging_officer = techjtblnew.grs
UNION 
SELECT mdt_userid AS logging_officer,
    'Last 90 Days' AS timespan,
    ACD_Time,
    TRUNCATE (( 1 - ( (TotalAssisting+TotalBRB+TotalShift+TotalLunch+TotalBreak-IF(TotalLunch<(DaysLoggedIn*Lunch),TotalLunch,(DaysLoggedIn*Lunch))-IF((TotalBRB+TotalBreak)<(DaysLoggedIn*1800),(TotalBRB+TotalBreak),(DaysLoggedIn*1800))) / (TotalLoginTime-TotalEreq-TotalDefault) ) ) *100,2) AS Utilization_percent,
    TRUNCATE((GRS_total/calls)*100,1) AS Ratio,
    IF (TotalACW =0,0,TotalACW / calls) AS ACW,
    grs.percent AS percent,
    TRUNCATE (((grs_total - wo_ci) / grs_total) *100,2) AS percent_w_ci,
    TRUNCATE (calls / ( ((TotalLoginTime-TotalEreq-TotalDefault) /3600) / 8.75 ) ,2) AS call_per_hour,
    TRUNCATE (GRS_total / ( ((TotalLoginTime-TotalEreq-TotalDefault) /3600) / 8.75 ) ,2) AS grs_per_hour 
FROM (SELECT DISTINCT fullname,
            SUM( IF (ReasonCode =  '138',  `ReasonCodeDuration` , 0) ) AS TotalAssisting,
            SUM( IF (ReasonCode =  '146',  `ReasonCodeDuration` , 0) ) AS TotalBRB,
            SUM( IF (ReasonCode =  '143',  `ReasonCodeDuration` , 0) ) AS TotalShift,
            SUM( IF (ReasonCode =  '141',  `ReasonCodeDuration` , 0) ) AS TotalACW,
            SUM( IF (ReasonCode =  '231',  `ReasonCodeDuration` , 0) ) AS TotalEreq,
            SUM( IF (ReasonCode =  '0',  `ReasonCodeDuration` , 0) ) AS TotalDefault,
            COUNT(ReasonCode = '136') AS CountLunch,
            SUM( IF (ReasonCode =  '136',  `ReasonCodeDuration` , 0) ) AS TotalLunch,
            SUM( IF (ReasonCode =  '137',  `ReasonCodeDuration` , 0) ) AS TotalBreak,
            SUM(  `ReasonCodeDuration` ) AS NRduration
        FROM  `CiscoAgentNotready` 
        WHERE StartDate >= '".adjustdate($DateTo,0,0,-90)." 00:00:00' 
                AND StartDate <= '".$DateTo." 23:59:59'
        GROUP BY fullname)
        AS notready, 
    (SELECT DISTINCT agentname,
            SUM( loginduration ) AS TotalLoginTime, COUNT(Date(logondate)) as DaysLoggedIn
        FROM CiscoAgentLogintime
        WHERE logondate  >= '".adjustdate($DateTo,0,0,-90)." 00:00:00' 
                AND logondate  <= '".$DateTo." 23:59:59'
        GROUP BY agentname)
        AS logintime, 
    (SELECT DISTINCT full_name, 
            SUM( handled ) AS calls
        FROM  `CiscoAgentCalls` 
        WHERE DateCol   >= '".adjustdate($DateTo,0,0,-90)."'  
                AND DateCol   <= '".$DateTo."'
        GROUP BY full_name)
        AS calls, 
    (SELECT DISTINCT logging_officer, 
            SUM( first_call ) AS firstcall, 
            SUM(IF (Config_item =  'unknown', 1, 0) ) AS wo_ci,
            COUNT( * ) AS GRS_total, 
            TRUNCATE ((SUM( first_call ) / COUNT( * )) *100,2) AS percent
        FROM (SELECT logging_officer, 
                IF (logging_officer =  `Resolving_Officer` , 1, 0) AS first_call, 
                Config_item
            FROM  `callcentergrsdata` 
            WHERE log_Date >= '".adjustdate($DateTo,0,0,-90)." 00:00:00' 
                 AND log_Date <= '".$DateTo." 23:59:59') 
            AS a
        GROUP BY logging_officer) 
        AS grs,
    (SELECT DISTINCT agtName,
            SUM(TalkTime) as sumTalk,
            SUM(CallsHandled) as answered,
            SUM(TalkTime)/SUM(CallsHandled) as ACD_Time
        FROM (SELECT CONCAT( LastName,  ', ', FirstName ) AS agtName,
                TalkTime, 
                CallsHandled
            FROM `CiscoAgentAHT`
            WHERE DateCol   >= '".adjustdate($DateTo,0,0,-90)."'  
                AND DateCol   <= '".$DateTo."') as subAHT
        GROUP BY agtName) 
        AS AHT,
    techjtblnew
WHERE mdt_userid = '".$user."'
AND notready.fullname = logintime.agentname
AND calls.full_name = notready.fullname 
AND calls.full_name = AHT.agtName
AND techjtblnew.cisco = notready.fullname 
AND grs.logging_officer = techjtblnew.grs
UNION 
SELECT mdt_userid AS logging_officer,
    'Last 120 Days' AS timespan,
    ACD_Time,
    TRUNCATE (( 1 - ( (TotalAssisting+TotalBRB+TotalShift+TotalLunch+TotalBreak-IF(TotalLunch<(DaysLoggedIn*Lunch),TotalLunch,(DaysLoggedIn*Lunch))-IF((TotalBRB+TotalBreak)<(DaysLoggedIn*1800),(TotalBRB+TotalBreak),(DaysLoggedIn*1800))) / (TotalLoginTime-TotalEreq-TotalDefault) ) ) *100,2) AS Utilization_percent,
    TRUNCATE((GRS_total/calls)*100,1) AS Ratio,
    IF (TotalACW =0,0,TotalACW / calls) AS ACW,
    grs.percent AS percent,
    TRUNCATE (((grs_total - wo_ci) / grs_total) *100,2) AS percent_w_ci,
    TRUNCATE (calls / ( ((TotalLoginTime-TotalEreq-TotalDefault) /3600) / 8.75 ) ,2) AS call_per_hour,
    TRUNCATE (GRS_total / ( ((TotalLoginTime-TotalEreq-TotalDefault) /3600) / 8.75 ) ,2) AS grs_per_hour 
FROM (SELECT DISTINCT fullname,
            SUM( IF (ReasonCode =  '138',  `ReasonCodeDuration` , 0) ) AS TotalAssisting,
            SUM( IF (ReasonCode =  '146',  `ReasonCodeDuration` , 0) ) AS TotalBRB,
            SUM( IF (ReasonCode =  '143',  `ReasonCodeDuration` , 0) ) AS TotalShift,
            SUM( IF (ReasonCode =  '141',  `ReasonCodeDuration` , 0) ) AS TotalACW,
            SUM( IF (ReasonCode =  '231',  `ReasonCodeDuration` , 0) ) AS TotalEreq,
            SUM( IF (ReasonCode =  '0',  `ReasonCodeDuration` , 0) ) AS TotalDefault,
            COUNT(ReasonCode = '136') AS CountLunch,
            SUM( IF (ReasonCode =  '136',  `ReasonCodeDuration` , 0) ) AS TotalLunch,
            SUM( IF (ReasonCode =  '137',  `ReasonCodeDuration` , 0) ) AS TotalBreak,
            SUM(  `ReasonCodeDuration` ) AS NRduration
        FROM  `CiscoAgentNotready` 
        WHERE StartDate >= '".adjustdate($DateTo,0,0,-120)." 00:00:00' 
                AND StartDate <= '".$DateTo." 23:59:59'
        GROUP BY fullname)
        AS notready, 
    (SELECT DISTINCT agentname,
            SUM( loginduration ) AS TotalLoginTime, COUNT(Date(logondate)) as DaysLoggedIn
        FROM CiscoAgentLogintime
        WHERE logondate  >= '".adjustdate($DateTo,0,0,-120)." 00:00:00' 
                AND logondate  <= '".$DateTo." 23:59:59'
        GROUP BY agentname)
        AS logintime, 
    (SELECT DISTINCT full_name, 
            SUM( handled ) AS calls
        FROM  `CiscoAgentCalls` 
        WHERE DateCol   >= '".adjustdate($DateTo,0,0,-120)."'  
                AND DateCol   <= '".$DateTo."'
        GROUP BY full_name)
        AS calls, 
    (SELECT DISTINCT logging_officer, 
            SUM( first_call ) AS firstcall, 
            SUM(IF (Config_item =  'unknown', 1, 0) ) AS wo_ci,
            COUNT( * ) AS GRS_total, 
            TRUNCATE ((SUM( first_call ) / COUNT( * )) *100,2) AS percent
        FROM (SELECT logging_officer, 
                IF (logging_officer =  `Resolving_Officer` , 1, 0) AS first_call, 
                Config_item
            FROM  `callcentergrsdata` 
            WHERE log_Date >= '".adjustdate($DateTo,0,0,-120)." 00:00:00' 
                 AND log_Date <= '".$DateTo." 23:59:59') 
            AS a
        GROUP BY logging_officer) 
        AS grs,
    (SELECT DISTINCT agtName,
            SUM(TalkTime) as sumTalk,
            SUM(CallsHandled) as answered,
            SUM(TalkTime)/SUM(CallsHandled) as ACD_Time
        FROM (SELECT CONCAT( LastName,  ', ', FirstName ) AS agtName,
                TalkTime, 
                CallsHandled
            FROM `CiscoAgentAHT`
            WHERE DateCol   >= '".adjustdate($DateTo,0,0,-120)."'  
                AND DateCol   <= '".$DateTo."') as subAHT
        GROUP BY agtName) 
        AS AHT,
    techjtblnew
WHERE mdt_userid = '".$user."'
AND notready.fullname = logintime.agentname
AND calls.full_name = notready.fullname 
AND calls.full_name = AHT.agtName
AND techjtblnew.cisco = notready.fullname 
AND grs.logging_officer = techjtblnew.grs

Ответы [ 2 ]

0 голосов
/ 07 февраля 2012

Похоже, вы могли бы уйти со сложной группировкой.Например, вот общий способ сделать это с записями:

SELECT
  count(*),
  MIN(creation)
FROM record
WHERE creation > CURDATE() - INTERVAL 120 DAY
GROUP BY 
 IF(creation>CURDATE() - INTERVAL 30 DAY,'030',
   IF(creation>CURDATE() - INTERVAL 90 DAY,'090',
     IF(creation>CURDATE() - INTERVAL 120 DAY,'120',
       'OLDER'
     )
   )
 )

Вы можете добавить записи по мере необходимости, поскольку каждый диапазон является эксклюзивным.

Вот пример выходных данных:

+----------+---------------+
| count(*) | MIN(creation) |
+----------+---------------+
|     1472 | 2012-01-08    |
|     2336 | 2011-11-09    |
|     1528 | 2011-10-10    |
|     5336 | 2011-10-10    |
+----------+---------------+
4 rows in set (0.13 sec)
0 голосов
/ 01 февраля 2012

Да.Просто запросите данные за последние 180 дней и проанализируйте их на программном уровне.

Если вам нужен индикатор того, какой из них находится в каждой строке, вы можете использовать операторы CASE или IF:

http://dev.mysql.com/doc/refman/5.0/en/if-statement.html

IF search_condition THEN statement_list
    [ELSEIF search_condition THEN statement_list] ...
    [ELSE statement_list]
END IF

http://dev.mysql.com/doc/refman/5.0/en/case-statement.html

CASE case_value
    WHEN when_value THEN statement_list
    [WHEN when_value THEN statement_list] ...
    [ELSE statement_list]
END CASE

ОБНОВЛЕНИЕ

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

Я не думаю, что есть выход из выполнения UNION НО вас, если вы сделаете UNIONзаблаговременно добавляя столбец для различных интервалов времени, вы можете просто один раз запросить результаты.

В этом примере я создаю столбец с именем span во время UNION.t1 является результирующей «таблицей».Поскольку span отличается для каждого диапазона дат, строки будут отображаться несколько раз.

Пример таблицы:

mysql> select * from test;
+----+------------+
| id | when       |
+----+------------+
|  1 | 2012-02-01 |
|  2 | 2012-01-01 |
|  3 | 2011-09-01 |
+----+------------+

Запрос с объединениями:

mysql> 
    ->    SELECT *, 1 as 'span' FROM `test` WHERE `when` > '2012-01-15'
    -> UNION
    ->    SELECT *, 2 as 'span' FROM `test` WHERE `when` > '2011-12-15'
    -> UNION
    ->    SELECT *, 3 as 'span' FROM `test` WHERE `when` > '2011-08-15';

+----+------------+------+
| id | when       | span |
+----+------------+------+
|  1 | 2012-02-01 |    1 |
|  2 | 2012-01-01 |    2 |
|  1 | 2012-02-01 |    2 |
|  3 | 2011-09-01 |    3 |
|  2 | 2012-01-01 |    3 |
|  1 | 2012-02-01 |    3 |
+----+------------+------+

Запрос с использованием этого объединения (пользовательские SELECT и WHERE t1.id > 0):

mysql> 
    -> SELECT
    ->    `id`,
    ->    `when`,
    ->    if(`span` = 1, 'Last 30 Days',
    ->       if(`span` = 2, 'Last 60 Days',
    ->          'Last 180 Days')) as 'Timespan'
    -> FROM (
    ->       SELECT *, 1 as 'span' FROM `test` WHERE `when` > '2012-01-15'
    ->    UNION
    ->       SELECT *, 2 as 'span' FROM `test` WHERE `when` > '2011-12-15'
    ->    UNION
    ->       SELECT *, 3 as 'span' FROM `test` WHERE `when` > '2011-08-15'
    -> ) as t1
    -> WHERE t1.id > 0;

+----+------------+---------------+
| id | when       | Timespan      |
+----+------------+---------------+
|  1 | 2012-02-01 | Last 30 Days  |
|  2 | 2012-01-01 | Last 60 Days  |
|  1 | 2012-02-01 | Last 60 Days  |
|  3 | 2011-09-01 | Last 180 Days |
|  2 | 2012-01-01 | Last 180 Days |
|  1 | 2012-02-01 | Last 180 Days |
+----+------------+---------------+

Все ваши запросы будут выполняться только с t1, а не с самой таблицы.Добавление дополнительного столбца при создании t1 позволяет каждой строке появляться несколько раз, поскольку дополнительная строка делает ее уникальной.

...