简体   繁体   English

是否可以使用mysql通过单个查询选择多个重叠的日期范围?

[英]Is it possible to select multiple overlapping date ranges with a single query using mysql?

I currently have a somewhat large SQL statement that UNIONs the same SELECT statement 3 times each time with a larger date range. 我目前有一个较大的SQL语句,它每次在较大的日期范围内都对同一个SELECT语句进行3次UNION。 IE Last 30 days, Last 90 Days and Last 180 Days. IE过去30天,过去90天和过去180天。 The SQL works just fine and I am even OK with the fact that the query takes quite a while to run, I am just wondering if there is anyway to do the same thing with just one SELECT statement. SQL运行正常,我什至可以接受查询运行相当长一段时间的事实,我只是想知道是否只用一个SELECT语句就能做同样的事情。

Seeing as a couple of people asked to see my code:- 好像有几个人要求看我的代码:-

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

Yes. 是。 Just query for the last 180 days and parse it in the software layer. 只需查询最近的180天,然后在软件层中进行解析即可。

If you want an indicator of which one each row is, you can use CASE or IF statements: 如果要指示每行是哪一个,可以使用CASEIF语句:

http://dev.mysql.com/doc/refman/5.0/en/if-statement.html http://dev.mysql.com/doc/refman/5.0/zh-CN/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 http://dev.mysql.com/doc/refman/5.0/zh-CN/case-statement.html

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

UPDATE 更新

Ok, now that I know what you are going for I can provide a better solution that I believe will fit your needs. 好的,现在我知道您要做什么了,我可以提供一个更好的解决方案,我相信它将满足您的需求。

I don't think that there is a way out of doing UNION BUT you if you do the UNION ahead of time adding a column for the various time spans you can just query once on the results. 我不认为有一种方法做出来的UNION 你如果你做的UNION提前添加一列的各种时间跨度你可以只对结果查询一次。

In this example, I create a column called span during the UNION . 在此示例中,我在UNION期间创建了一个名为span的列。 The t1 is the resulting "table". t1是结果“表”。 Since span is different for each date range, the rows will show up multiple times. 由于每个日期范围的span都不同,因此这些行将显示多次。

Example Table: 示例表:

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

Query With Unions: 用联合查询:

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 |
+----+------------+------+

Query Using That Union (custom SELECT and WHERE t1.id > 0 ): 使用该联合查询(自定义SELECTWHERE 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 |
+----+------------+---------------+

You will do all of your query stuff off of t1 , not off the table itself. 您将根据t1而不是表本身进行所有查询。 Adding the extra column in the creation of t1 allows each row to appear multiple times as the extra row will cause it to be unique. 在创建t1添加额外的列可以使每一行出现多次,因为额外的行将使其唯一。

Seems like you could get away with a complex grouping. 似乎您可以通过复杂的分组来摆脱困境。 Eg, here's a generic way to do it with records: 例如,这是使用记录的通用方法:

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'
     )
   )
 )

You would want to add the records as you go, as each range is exclusive. 由于每个范围都是互斥的,因此您想随便添加记录。

Here's a sample output: 这是一个示例输出:

+----------+---------------+
| 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM