【问题标题】:Grouping my multiple columns for a single condiiton针对单个条件按多列分组
【发布时间】:2017-10-27 18:51:04
【问题描述】:

我在下面有一个查询正在运行,但不是我想要的。

该查询为我们的 CSR 提取电话数据,我们目前正在获取 15 个代理的数据。当前查询获得了我需要的总数,但将它们全部加起来并给了我一行总数。我想让它显示每个 CSR 的总数。这样做的问题是源表中的每个呼叫记录都有其 4 位数的扩展名作为主叫号码或被叫号码。但是,每条记录中都没有一个字段可以将该用户的分机与呼叫联系起来。它必须作为主叫号码或被叫号码存在。

所以我相信我的逻辑是正确的,除了现在我需要按分机对呼叫进行分组。因此,对于 15 个 CSR,我希望语句返回 15 行,每行都有自己的总计。但由于没有通用字段可供分组,我想我需要按两个字段进行分组。

换句话说,说“如果callingpartyno 有7200,finally calledpartyno 有7200,则将它们分组为分机7200 的总数”。

以下是数据在源表中的外观示例:

    callingpartyno | finallycalledpartyno 
    -------------------------------------
    1234                outside   
    1234                outside   
    1234                outside   
    outsidecall         1234          
    outsidecall         1234          
    outsidecall         1234          
    9876                outside   
    9876                outside   
    9876                outside   
    outsidecall         9876         
    outsidecall         9876                  
    outsidecall         9876                  

如您所见,没有任何东西将每条记录标识为同一个 CSR。

这里是查询:

 SELECT

        sum(Duration) AS total_talk_time_seconds
      , round(sum(Duration) / 60,2) AS total_talk_time_minutes
      , sum(if(LEGTYPE1 = 1,1,0)) AS total_outbound
      , sum(if(LEGTYPE1 = 2,1,0) and ANSWERED = 1) AS total_inbound
      , sum(if(LEGTYPE1 = 2,1,0) and ANSWERED = 0) AS total_missed
      , SUM(IF(LEGTYPE1 = 1, 1, 0)) +                   -- outbound calls
        SUM(IF(LEGTYPE1 = 2, 1, 0))  AS total_calls
      , NOW() AS time_of_report
      , curdate() AS date_of_report
FROM cdrdb.session a
    INNER JOIN cdrdb.callsummary b
      ON a.NOTABLECALLID = b.NOTABLECALLID
    where date(b.ts) = '2017-10-16 00:00:00'
    AND callingpartyno IN (7276,7314, 7295, 7306,7357,7200,7218,7247 7331,7255,7330,7000,7215, 7240,7358,7312) 
    OR  finallycalledpartyno IN (7276,7314, 7295, 7306,7357,7200,7218,7247 7331,7255,7330,7000,7215, 7240,7358,7312) 

因此,查询再次用于提取指定日期的记录,其中任何扩展名都在 callpartyno 或 finally calledpartyno 中,但我需要一种方法将其按这两个分组并将每条记录视为 4 位数扩展名,几乎就像一个用户 ID。

【问题讨论】:

  • GROUP BY 的“肮脏”技巧:GROUP BY callingpartyno + finallycalledpartyno。根据您的示例数据,两个字段之一将转换为0。但是,如果数字并不总是数字,这将不起作用。

标签: mysql sql


【解决方案1】:

这正是group by 子句的用途。通过插入case 语句,我们可以使用您自己的条件创建一个ID。

 select
  case 
    when callingpartyno       in (7276,7314,7295,7306,7357,7200,7218,7247,7331,7255,7330,7000,7215,7240,7358,7312)
      then callingpartyno
    when finallycalledpartyno in (7276,7314,7295,7306,7357,7200,7218,7247,7331,7255,7330,7000,7215,7240,7358,7312)
      then finallycalledpartyno
  end as id
  , sum(duration) as total_talk_time_seconds
  , round(sum(duration) / 60,2) as total_talk_time_minutes
  , sum(if(legtype1 = 1,1,0)) as total_outbound
  , sum(if(legtype1 = 2,1,0) and answered = 1) as total_inbound
  , sum(if(legtype1 = 2,1,0) and answered = 0) as total_missed
  , sum(if(legtype1 = 1, 1, 0)) +                   -- outbound calls
    sum(if(legtype1 = 2, 1, 0))  as total_calls
  , now() as time_of_report
  , curdate() as date_of_report
from 
  cdrdb.session a
  join cdrdb.callsummary b
    on a.notablecallid = b.notablecallid
where 
  date(b.ts) = '2017-10-16 00:00:00'
  and (
    callingpartyno           in (7276,7314,7295,7306,7357,7200,7218,7247,7331,7255,7330,7000,7215,7240,7358,7312)
    or  finallycalledpartyno in (7276,7314,7295,7306,7357,7200,7218,7247,7331,7255,7330,7000,7215,7240,7358,7312)
  )
group by
  id -- <-- the calculated field we created in the select clause

我还更正了您的 or 声明。像您一样在括号外使用它会使日期或多或少无关紧要。

【讨论】:

  • MySQL 允许您在 GROUP BY 子句中使用列别名。无需复制和粘贴长表达式。
  • @PaulSpiegel:更新
【解决方案2】:

我建议:

SELECT sum(Duration) AS total_talk_time_seconds,
       round(sum(Duration) / 60, 2) AS total_talk_time_minutes,
       sum(LEGTYPE1 = 1) AS total_outbound,
       sum(LEGTYPE1 = 2 and ANSWERED = 1) AS total_inbound,
       sum(LEGTYPE1 = 2 and ANSWERED = 0) AS total_missed,
       SUM(LEGTYPE1 in (1, 2)) AS total_calls,
       NOW() AS time_of_report,
       curdate() AS date_of_report
FROM cdrdb.session s INNER JOIN
     cdrdb.callsummary cs
      ON s.NOTABLECALLID = cs.NOTABLECALLID
where date(b.ts) = '2017-10-16' and
      (callingpartyno IN (7276, 7314, 7295, 7306, 7357, 7200,7218,7247, 7331, 7255, 7330, 7000, 7215, 7240,7358,7312)  or
       finallycalledpartyno IN (7276,7314, 7295, 7306,7357,7200, 7218,7247, 7331, 7255, 7330, 7000, 7215, 7240, 7358, 7312) 
      )
group by (case when callingpartyno IN (7276, 7314, 7295, 7306,7357, 7200, 7218, 7247, 7331,7255,7330,7000,7215, 7240,7358,7312)
               then callingpartyno else finallycalledpartyno
          end);

您真正的问题是 where 子句中的逻辑括号。

另外,我做了以下改动:

  • 删除了if()。如果要使用 MySQL 扩展,只需使用将布尔值视为整数的扩展即可。
  • 使用in 而不是链式比较
  • 无需在字符串文字中包含日期的时间部分。

【讨论】:

  • 这在逻辑上做得更好,但它仍然只返回所有总数的一行,而不是将每个呼叫的 4 位数分机视为单个用户分机。所以我需要它列出 15 行,每行包含每个扩展的总数
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-05
  • 1970-01-01
  • 2021-08-01
相关资源
最近更新 更多