我如何得到总数?

时间:2014-01-07 01:59:51

标签: sql oracle count sum oracle-sqldeveloper

我无法得到确切的查询来获得总表的总数。我想在call_time表中获取每个日期的总和。这是我的疑问:

SELECT call_type, channel, call_time,
       count (CASE WHEN upper(status) = upper('no answer') THEN 1 ELSE NULL END) AS cnt_no_answer,
       count (CASE WHEN upper(status) = upper('answered') THEN 1 ELSE NULL END) AS cnt_answer,
       count (status) AS cnt_total
FROM   app_account.cc_call
WHERE  channel = 'DAHDI/i1/'
AND    call_time BETWEEN ('30-DEC-2013') AND ('04-JAN-2014')
GROUP BY call_type, channel, call_time;

该查询的一些输出:

CALL_TYPE        CHANNEL    CALL_TIME CNT_NO_ANSWER  CNT_ANSWERED   CNT_TOTAL
LANDLINE         DAHDI/i1/  03-JAN-14     1            0               1
MOBILE-SUN       DAHDI/i1/  03-JAN-14     0            1               1
MOBILE-SUN       DAHDI/i1/  03-JAN-14     1            0               1
LANDLINE         DAHDI/i1/  03-JAN-14     1            0               1
LANDLINE         DAHDI/i1/  03-JAN-14     1            0               1
LANDLINE         DAHDI/i1/  03-JAN-14     1            0               1
MOBILE-SUN       DAHDI/i1/  02-JAN-14     1            0               1
MOBILE-SUN       DAHDI/i1/  02-JAN-14     0            1               1
LANDLINE         DAHDI/i1/  02-JAN-14     0            1               1
LANDLINE         DAHDI/i1/  02-JAN-14     1            0               1
MOBILE-SMART     DAHDI/i1/  02-JAN-14     1            0               1

我的例外输出:

CALL_TIME  CNT_NO_ANSWER CNT_ANSWERED
03-JAN-14   27             10   
02-JAN-14   48             20   

请帮帮我。

谢谢!

3 个答案:

答案 0 :(得分:4)

使用以下内容:

  SELECT CALL_TYPE, CHANNEL, TRUNC(CALL_TIME)
         , COUNT (CASE UPPER(STATUS)
                     WHEN UPPER('no answer') THEN 1
                     ELSE NULL
                  END) AS CNT_NO_ANSWER
         , COUNT (CASE UPPER(STATUS)
                       WHEN UPPER('answered') THEN 1
                       ELSE NULL
                  END) AS CNT_ANSWER
         , COUNT (STATUS) AS CNT_TOTAL
    FROM APP_ACCOUNT.CC_CALL
   WHERE CHANNEL = 'DAHDI/i1/'
     AND CALL_TIME BETWEEN TO_DATE('30-DEC-2013')
                       AND TO_DATE('04-JAN-2014')
GROUP BY CALL_TYPE, CHANNEL, TRUNC(CALL_TIME);

我所做的重大改变是TRUNC(CALL_TIME)。 Oracle将日期存储为日期时间值,其中包含日期和时间值。因此,当您使用GROUP BY ..., CALL_TIME, ...时,实际发生的是分组是针对日期时间值而不是日期值进行的。只有精确时间精确到几分之一秒的调用才会被组合在一起,这不是预期的行为。因此,当您必须按天显示分组时,请使用GROUP BY TRUNC(CALL_DATE)

修改

要获取每天的总计,您已在查询中使用COUNT(STATUS) AS CNT_TOTAL!如果列为非空并且为每个调用记录状态,它将为您提供总调用次数。如果此列包含空值,我建议您使用COUNT(*) AS CNT_TOTAL,因为它会计算所有行而不考虑列的约束。

就“每天”部分而言,TRUNC(datetime)函数可以将日期时间值从它们的年份截断到它们的分钟。这意味着,如果您想获得每年的通话次数或任何其他统计数据,那么您只需使用TRUNC(call_time, 'YYYY')即可。另一方面,如果您想要每小时的通话统计信息,可以使用TRUNC(call_time, 'HH')TRUNC(call_time, 'HH24')。同样一分钟。

但请注意,除非使用TO_CHAR函数显示日期,否则Toad或SQL Developer等前端开发工具会以DD-MON-YYYY格式显示日期时间值,并丢弃时间信息。这就是让你处于第一位的原因。因此,如果您通过将日期时间截断为一小时或一分钟进行分组,即使结果正确,您将看到DD-MON-YYYY格式的重复日期。因此,不要混淆。

如需进一步阅读TRUNC,我建议Oracle Docsthis link to techonthenet.com。对于TO_CHAROracle Docs here有详细且易于理解的解释。

答案 1 :(得分:3)

试试这个:

SELECT CALL_TYPE, CHANNEL, TRUNC(CALL_TIME)
      ,COUNT (CASE WHEN UPPER(STATUS) = UPPER('no answer') THEN 1 END) AS CNT_NO_ANSWER
      ,COUNT (CASE WHEN UPPER(STATUS) = UPPER('answered') THEN 1 END) AS CNT_ANSWER
      ,COUNT (STATUS) AS CNT_TOTAL
FROM APP_ACCOUNT.CC_CALL
WHERE CHANNEL = 'DAHDI/i1/'
AND CALL_TIME BETWEEN ('30-DEC-2013') AND ('04-JAN-2014')
GROUP BY CALL_TYPE, CHANNEL, TRUNC(CALL_TIME);

如果CALL_TIME包含时间值,并且您希望每个日期GROUP BY,则应trunc CALL_TIME为其日期。

答案 2 :(得分:3)

要获得按日计数,您需要与CALL_TIME进行分组。试试这样,

SELECT call_type, 
       channel, 
       trunc(call_time),
       count (CASE WHEN upper(status) = upper('no answer') THEN 1 ELSE NULL END) AS cnt_no_answer,
       count (CASE WHEN upper(status) = upper('answered') THEN 1 ELSE NULL END) AS cnt_answer
FROM   happ_account.cc_call
WHERE  channel = 'DAHDI/i1/'
AND    call_time BETWEEN to_date('30-DEC-2013', 'DD-MON-YYYY') AND to_date('04-JAN-2014', 'DD-MON-YYYY')
GROUP BY call_type, channel, trunc(call_time);