在Oracle中更新日期计数

时间:2014-01-12 07:24:01

标签: sql oracle plsql oracle11g oracle10g

我有一个奇怪的要求。这里是。我有一张桌子。

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是单独的列。如果我没有正确解释,我道歉。

任何建议或方法如何实现这一点。感谢您耐心地调查我的问题。任何帮助将不胜感激。

3 个答案:

答案 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 ;

我担心查询性能。采用这种方法是否合适?