我有一个奇怪的要求。这里是。我有一张桌子。
DateTime PhoneNo Network
------------------- -------- ---------
11/01/2014 13:05:45 99999999 NetTwo
11/01/2014 13:05:45 99999999 NetOne
11/01/2014 13:05:45 99999999 NetOne
12/01/2014 13:05:45 99999999 NetOne
12/01/2014 13:06:45 99999999 NetOne
12/01/2014 13:07:45 88888888 NetTwo
12/01/2014 13:08:45 77777777 NetThree
我必须每天运行一次存储过程来更新另一个表,以便计算调用者调用一天的次数摘要,并将其更新到相应的列
destinationTable会:
Date Month year Phone Network 01 02 03 -------11-12---30-31
11/01/2014 JAN 2014 99999999 NetOne 0 0 0 2 0 0 0
11/01/2014 JAN 2014 99999999 NetTwo 0 0 0 1 0 0 0
12/01/2014 JAN 2014 99999999 NetTwo 0 0 0 0 2 0 0
12/01/2014 JAN 2014 88888888 NetTwo 0 0 0 0 1 0 0
12/01/2014 JAN 2014 77777777 NetTwo 0 0 0 0 1 0 0
这里01到31是单独的列。如果我没有正确解释,我道歉。
任何建议或方法如何实现这一点。感谢您耐心地调查我的问题。任何帮助将不胜感激。
答案 0 :(得分:0)
这并不奇怪 - 它被称为数据透视表
这是一种方法
select trunc(DateTime) as date , to_char(datetimem,'MON') as month , to_number(to_char(datetime,'yyyy')) as year , PhoneNo, network ,
sum(case when to_char(DateTime,'hh24') = 0 then 1 else 0 end) as h00,
sum(case when to_char(DateTime,'hh24') = 1 then 1 else 0 end) as h01,
..
sum(case when to_char(DateTime,'hh24') = 23 then 1 else 0 end) as h23
from calls_tables
group by trunc(DateTime) , to_char(datetimem,'MON'), to_number(to_char(datetime,'yyyy')) , PhoneNo, network
11g也有枢轴功能。
你应该搜索它。
答案 1 :(得分:0)
对于定期更新,最好使用MERGE
语句。
首先,下面的代码示例的初始设置:
create table SourceTable(
DateTime date,
PhoneNo varchar2(40),
Network varchar2(20)
);
create table DestinationTable(
CallDate date,
CallMonth varchar2(20),
CallYear number,
Phone varchar2(40),
Network varchar2(20),
d01 number,
d02 number,
d03 number,
d04 number,
d05 number,
d06 number,
d07 number,
d08 number,
d09 number,
d10 number,
d11 number,
d12 number,
d13 number,
d14 number,
d15 number,
d16 number,
d17 number,
d18 number,
d19 number,
d20 number,
d21 number,
d22 number,
d23 number,
d24 number,
d25 number,
d26 number,
d27 number,
d28 number,
d29 number,
d30 number,
d31 number
);
字段名称已更改为符合标准命名规则。
SQLFiddle中提供的架构设置和代码。
接下来,查询以演示从源表中提取日期和时间部分以使用目标:
select
trunc(call_log.DateTime) CallDate,
to_char(call_log.DateTime,'MON','NLS_DATE_LANGUAGE=ENGLISH') CallMonth,
extract(year from call_log.DateTime) CallYear,
extract(day from call_log.DateTime) CallDay,
PhoneNo Phone,
Network Network
from
SourceTable call_log
order by
datetime, phoneno, network
根据日期,网络和电话号码,可以对源表中的数据进行分组,并为合并生成源数据:
select
CallDate,
to_char(CallDate,'MON','NLS_DATE_LANGUAGE=ENGLISH') CallMonth,
extract(year from CallDate) CallYear,
d01, d02, d03, d04, d05, d06, d07, d08, d09, d10,
d11, d12, d13, d14, d15, d16, d17, d18, d19, d20,
d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31
from (
select
CallDate,
Phone,
Network,
sum(decode(callDay, 1,1,0)) d01,
sum(decode(callDay, 2,1,0)) d02,
sum(decode(callDay, 3,1,0)) d03,
sum(decode(callDay, 4,1,0)) d04,
sum(decode(callDay, 5,1,0)) d05,
sum(decode(callDay, 6,1,0)) d06,
sum(decode(callDay, 7,1,0)) d07,
sum(decode(callDay, 8,1,0)) d08,
sum(decode(callDay, 9,1,0)) d09,
sum(decode(callDay,10,1,0)) d10,
sum(decode(callDay,11,1,0)) d11,
sum(decode(callDay,12,1,0)) d12,
sum(decode(callDay,13,1,0)) d13,
sum(decode(callDay,14,1,0)) d14,
sum(decode(callDay,15,1,0)) d15,
sum(decode(callDay,16,1,0)) d16,
sum(decode(callDay,17,1,0)) d17,
sum(decode(callDay,18,1,0)) d18,
sum(decode(callDay,19,1,0)) d19,
sum(decode(callDay,20,1,0)) d20,
sum(decode(callDay,21,1,0)) d21,
sum(decode(callDay,22,1,0)) d22,
sum(decode(callDay,23,1,0)) d23,
sum(decode(callDay,24,1,0)) d24,
sum(decode(callDay,25,1,0)) d25,
sum(decode(callDay,26,1,0)) d26,
sum(decode(callDay,27,1,0)) d27,
sum(decode(callDay,28,1,0)) d28,
sum(decode(callDay,29,1,0)) d29,
sum(decode(callDay,30,1,0)) d30,
sum(decode(callDay,31,1,0)) d31
from (
select
trunc(call_log.DateTime) CallDate,
extract(day from call_log.DateTime) CallDay,
PhoneNo Phone,
Network Network
from
SourceTable call_log
)
group by
CallDate, Phone, Network
)
order by
CallDate, Phone, Network
最后一步是将准备好的数据合并到目标表中:
merge into DestinationTable call_totals
using (
select -- Previous select (removed unneeded columns and ordering)
CallDate,
Phone,
Network,
sum(decode(callDay, 1,1,0)) d01,
sum(decode(callDay, 2,1,0)) d02,
sum(decode(callDay, 3,1,0)) d03,
sum(decode(callDay, 4,1,0)) d04,
sum(decode(callDay, 5,1,0)) d05,
sum(decode(callDay, 6,1,0)) d06,
sum(decode(callDay, 7,1,0)) d07,
sum(decode(callDay, 8,1,0)) d08,
sum(decode(callDay, 9,1,0)) d09,
sum(decode(callDay,10,1,0)) d10,
sum(decode(callDay,11,1,0)) d11,
sum(decode(callDay,12,1,0)) d12,
sum(decode(callDay,13,1,0)) d13,
sum(decode(callDay,14,1,0)) d14,
sum(decode(callDay,15,1,0)) d15,
sum(decode(callDay,16,1,0)) d16,
sum(decode(callDay,17,1,0)) d17,
sum(decode(callDay,18,1,0)) d18,
sum(decode(callDay,19,1,0)) d19,
sum(decode(callDay,20,1,0)) d20,
sum(decode(callDay,21,1,0)) d21,
sum(decode(callDay,22,1,0)) d22,
sum(decode(callDay,23,1,0)) d23,
sum(decode(callDay,24,1,0)) d24,
sum(decode(callDay,25,1,0)) d25,
sum(decode(callDay,26,1,0)) d26,
sum(decode(callDay,27,1,0)) d27,
sum(decode(callDay,28,1,0)) d28,
sum(decode(callDay,29,1,0)) d29,
sum(decode(callDay,30,1,0)) d30,
sum(decode(callDay,31,1,0)) d31
from (
select
trunc(call_log.DateTime) CallDate,
extract(day from call_log.DateTime) CallDay,
PhoneNo Phone,
Network Network
from
SourceTable call_log
)
group by
CallDate, Phone, Network
) existing_calls
on (
-- Link prepared data from source table to destination
call_totals.CallDate = existing_calls.CallDate
and
call_totals.Phone = existing_calls.Phone
and
call_totals.Network = existing_calls.Network
)
when matched then
-- If record for date, phone and record found - update statistics
update
set
d01 = existing_calls.d01,
d02 = existing_calls.d02,
d03 = existing_calls.d03,
d04 = existing_calls.d04,
d05 = existing_calls.d05,
d06 = existing_calls.d06,
d07 = existing_calls.d07,
d08 = existing_calls.d08,
d09 = existing_calls.d09,
d10 = existing_calls.d10,
d11 = existing_calls.d11,
d12 = existing_calls.d12,
d13 = existing_calls.d13,
d14 = existing_calls.d14,
d15 = existing_calls.d15,
d16 = existing_calls.d16,
d17 = existing_calls.d17,
d18 = existing_calls.d18,
d19 = existing_calls.d19,
d20 = existing_calls.d20,
d21 = existing_calls.d21,
d22 = existing_calls.d22,
d23 = existing_calls.d23,
d24 = existing_calls.d24,
d25 = existing_calls.d25,
d26 = existing_calls.d26,
d27 = existing_calls.d27,
d28 = existing_calls.d28,
d29 = existing_calls.d29,
d30 = existing_calls.d30,
d31 = existing_calls.d31
when not matched then
-- If record for date, phone and record not found - add new one
insert (
CallDate, CallMonth, CallYear, Phone, Network,
d01, d02, d03, d04, d05, d06, d07, d08, d09, d10,
d11, d12, d13, d14, d15, d16, d17, d18, d19, d20,
d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31
) values (
existing_calls.CallDate,
to_char(existing_calls.CallDate, 'MON', 'NLS_DATE_LANGUAGE=ENGLISH'),
extract( year from existing_calls.CallDate),
existing_calls.Phone,
existing_calls.Network,
existing_calls.d01,
existing_calls.d02,
existing_calls.d03,
existing_calls.d04,
existing_calls.d05,
existing_calls.d06,
existing_calls.d07,
existing_calls.d08,
existing_calls.d09,
existing_calls.d10,
existing_calls.d11,
existing_calls.d12,
existing_calls.d13,
existing_calls.d14,
existing_calls.d15,
existing_calls.d16,
existing_calls.d17,
existing_calls.d18,
existing_calls.d19,
existing_calls.d20,
existing_calls.d21,
existing_calls.d22,
existing_calls.d23,
existing_calls.d24,
existing_calls.d25,
existing_calls.d26,
existing_calls.d27,
existing_calls.d28,
existing_calls.d29,
existing_calls.d30,
existing_calls.d31
)
;
答案 2 :(得分:0)
非常感谢你的努力。谢谢haki和Thinkjet。 @think:我从你那里学到了合并:D ..
我使用with子句的结果集中的子查询得到了我的预期结果。
WITH MainFilter(CLI,DAYS,COUNTS)
AS (SELECT TBL_DTL_CALLACTIVITY.CLI,
TO_CHAR(TBL_DTL_CALLACTIVITY.CALLSTARTTIME, 'DD'),COUNT(TBL_DTL_CALLACTIVITY.CLI)
FROM TBL_DTL_CALLACTIVITY
WHERE UPPER(TO_CHAR(TBL_DTL_CALLACTIVITY.CALLSTARTTIME, 'mon')) =UPPER(i_Month) AND
(SELECTED_DNIS IS NULL OR TBL_DTL_CALLACTIVITY.DNIS = SELECTED_DNIS)
GROUP BY TBL_DTL_CALLACTIVITY.CLI,
TO_CHAR(TBL_DTL_CALLACTIVITY.CALLSTARTTIME,'DD'))
SELECT MF.CLI,
NVL((SELECT COUNTS FROM MainFilter WHERE MainFilter.DAYS = '01' AND CLI = MF.CLI ),0) AS Day_01,
NVL((SELECT COUNTS FROM MainFilter WHERE MainFilter.DAYS = '02' AND CLI = MF.CLI ),0) AS Day_02,
NVL((SELECT COUNTS FROM MainFilter WHERE MainFilter.DAYS = '03' AND CLI = MF.CLI ),0) AS Day_03,
--------------------
--------------------
FROM MainFilter MF GROUP BY MF.CLI ;
我担心查询性能。采用这种方法是否合适?