我无法得到确切的查询来获得总表的总数。我想在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
请帮帮我。
谢谢!
答案 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 Docs和this link to techonthenet.com。对于TO_CHAR
,Oracle 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);