2012-01-02 5 views
2

특정 맞춤 기간별로 요약 된 요약 통계를 계산해야한다는 요구 사항이 있습니다. 특히 레스토랑 체인은 24 시간 운영됩니다. 나는 기간별 총 판매량과 같은 통계를 계산할 필요가있다. 기간은 "아침", "점심", "저녁"및 "밤"이다. 이 회사의 경우 통계를 추적하는 공식 날짜는 저녁 식사 후에 시작됩니다. 따라서 공휴일을 구성하는 24 시간은 오후 8시에 시작하여 오후 8시 (CST)까지 실행됩니다. 그것은 한 기간입니다. 또 다른 기간은 오후 8 시부 터 5시 30 분까지 "밤새도록"입니다. 나는 "TDEF"과 같이이라는 테이블로 이러한 정의를 넣어 :오라클 시간 기반 분석

drop table tdef cascade constraints 
; 

create table tdef 
(
    cd char(3) not null, 
    start_ts date not null, 
    stop_ts date not null 
) 

그리고 나는 시작 날짜가 항상 1900년 1월 1일에 시작 날짜로 저장된 TDEF 테이블에 정의를 삽입하고,이 걸쳐있는 경우 마찬가지로, 1 월 2 일 끝나는 1900. 그래서,

insert into tdef (start_ts, stop_ts, cd) 
values 
(
to_date('1900/01/01 20:00:00', 'yyyy/mm/dd hh24:mi:ss'), 
to_date('1900/01/02 19:59:59', 'yyyy/mm/dd hh24:mi:ss'), 
'24H' 
); 

insert into tdef (start_ts, stop_ts, cd) 
values 
(
to_date('1900/01/01 10:30:00', 'yyyy/mm/dd hh24:mi:ss'), 
to_date('1900/01/01 13:29:59', 'yyyy/mm/dd hh24:mi:ss'), 
'LUN 
); 

insert into tdef (start_ts, stop_ts, cd) 
values 
(
to_date('1900/01/01 15:30:00', 'yyyy/mm/dd hh24:mi:ss'), 
to_date('1900/01/02 08:29:59', 'yyyy/mm/dd hh24:mi:ss'), 
'ON' 
); 

나는 모든 등록 거래를 포함하는 매우 큰 테이블 (약 25 억 행)이 있습니다. 필자는 날짜 별 매출 (요약 8 PM ~ 8PM), 제품 및 시간 차원을 요약하여이를 빠른 액세스보고를 위해 테이블에 저장해야합니다. 표는 다음과 같아야합니다

여기
Dec 12 2011, Hamburger, 24H, 1000 
Dec 12 2011, Hamburger, ON, 100 
Dec 12 2011, Hamburger, LUN, 400 

내가이를 위해 한 일이다, 나는 1900 년에 트랜잭션의 시간과 어떤 거래 테이블에 두 개의 날짜 열을 추가 1/2/1900, 이렇게 :

to_date(concat('01/01/1900 ', tran_tm), 'mm/dd/yyyy hh24:mi'), 
to_date(concat('01/02/1900 ', tran_tm), 'mm/dd/yyyy hh24:mi') 

나는이 두 열을 색인화했습니다. 그런 다음 트랜잭션 ID와 시간 코드가 연관된 테이블을 작성했습니다. 각 트랜잭션 코드는 둘 이상의 시간 정의에있을 수 있습니다. 그래서 다음과 같습니다

24H, 1 
24H, 2 
24H, 3 
... 
LUN, 100 
LUN, 101 
LUN, 102 
... 
ON, 1 
ON, 2 
... 

나는 이러한 목표를 달성하기 위해 두 삽입을 선택 문을 사용 :

select t.trans_id, td.cd, to_date(to_char(to_date(concat(to_char(ts, 'mm/dd/yyyy '), to_char(td.stop_ts, 'hh24:mi:ss')), 'mm/dd/yyyy hh24:mi:ss', 'yyyymmdd'), 'yyyymmdd') 
from trans t, tdef td 
where ts1 >= td.start_ts and ts1 <= td.stop_ts 

select t.trans_id, td.cd, to_date(to_char(to_date(concat(to_char(ts, 'mm/dd/yyyy '), to_char(td.stop_ts, 'hh24:mi:ss')), 'mm/dd/yyyy hh24:mi:ss', 'yyyymmdd'), 'yyyymmdd') 
from trans t, tdef td 
where ts2 >= td.start_ts and ts2 <= td.stop_ts 

세 번째 필드는 "공식적인 날"입니다. 이것이 작동하는 방식은 트랜잭션이 2011 년 12 월 12 일 오후 8:01에 발생했다고 가정하고, ts1 필드는 1/1/1900 8:01 PM이고 ts2 필드는 오후 1:30/오후 8:01 PM이됩니다. 첫 번째 쿼리에서이 필드는 cd '24H'및 'ON'에 참여합니다. 공식 날짜는 '24H'의 경우 2011 년 12 월 13 일과 'ON'의 경우 12/13/2011로 계산됩니다. 이 트랜잭션은 날짜 범위를 벗어나기 때문에 두 번째 쿼리에 참여하지 않습니다. 거래가 2012 년 12 월 13 일 오후 12:05에 발생했다고 가정합니다. 첫 번째 쿼리에서 ts1은 다음과 같이 가입합니다 : 2011 년 12 월 13 일의 날짜는 '24H'이고, 2011 년 12 월 13 일의 날짜는 'LUN'입니다. 나는이 테이블을 일단

, 집계하기 쉬운 :이 솔루션이 작동하는 것으로 나타납니다

select tdef_trans.dt, sum(sales) from trans, tdef_trans where trans.id = tdef_trans.id and tdef_trans.cd = 'LUN' 

있지만, 나는이 일을 더 우아한 방법이 베팅하고있다. 어떤 아이디어?

+0

이 숙제가 있습니까? – eaolson

+0

아니요 숙제가 아닙니다. 실생활. 대부분의 사람들이 이해한다고 생각하는 산업이기 때문에이 개념을 레스토랑에 적용하여 상황을 일부 수정했습니다. 실제로이 데이터는 온라인 경매를 통해 얻은 것으로서, 이해하기 어려운 상황이라고 생각합니다. –

답변

2

데이터웨어 하우징을 수행하려는 경우 (그 것처럼 들릴 수도 있음), 하루 중 매 순간 테이블이 속한 테이블을 만드는 것이 가장 쉽습니다. 그것은 86400 행만있을 것입니다.

는 그런 다음 쿼리를 지불하는 가파른 가격처럼 보인다 비교적 간단한 사업 기간 트랜잭션의 두 번째 매핑하는 트랜잭션 테이블의 모든 레코드에 대한 I/O를 추가하는이 시간 차원

+0

감사합니다. 나는이 아이디어가 마음에 든다. 그러나이 방법을 사용하여 한밤의 장벽을 넘어서는 "공식적인 날"을 어떻게 처리해야하는지 명확하지 않습니다. 또는 자정 장벽을 가로 지르는 기간. –

+0

장벽을 가로 지르는 기간은 각 두 번째 기간이 어느 기간인지를 나타내므로 문제가되지 않습니다. 두 번째 86399는 두 번째 0과 마찬가지로 "24H"에 있습니다. "공식"날에 대해서는 합리적인 신기원 이후의 매일 행은 합리적으로 먼 미래까지 (여전히 연간 365.25 행). 각 행에서 "공식적인 날"의 시작 및 종료 타임 스탬프를 저장할 수 있습니다 (많은 다른 것들 중에서). 단 하나의 경계 만 포함됩니다. 해당 열의 날짜 차원에 가입하면 거래가 속한 "공식 날짜"가 표시됩니다. – rejj

+0

감사합니다. 따라서 올바르게 이해한다면이 sql :'select to_date ('19900101', 'YYYYMMDD') + numtodsinterval (n, 'day') 'dt'에서 to_date (concat (to_char) start_ts "로 (to_date ('19900101', 'YYYYMMDD') + numtodsinterval (n-1, 'day'), 'YYYYMMDD'), '20:00:00'), 'YYYYMMDD HH24 : MI : SS' (YYYYMMDD), 'YYYYMMDD'), 'YYYYMMDD HH24 : MI : SS'), to_date (concat ('19900101', 'YYYYMMDD') + numtodsinterval (n, 'day' "stop_ts"from (듀얼에서 레벨 n 선택 레벨 <= 7305)' –

1

에 가입된다 .아마도 당신은 대신에 아래의 쿼리처럼 데이터를 저장하고 피벗 수 :

select case 
     when txn_ts - trunc(txn_ts) > numtodsinterval(20, 'hour') 
      then trunc(txn_ts) + 1 
      else trunc(txn_ts)  
     end as business_day, 
     sum (case when ( txn_ts - trunc(txn_ts) > numtodsinterval(20, 'hour') 
         or txn_ts - trunc(txn_ts) < numtodsinterval(5.5, 'hour') 
       then txn_amt else 0 end) as overnight_sales, 
     sum (case when ( txn_ts - trunc(txn_ts) >= numtodsinterval(5.5, 'hour') 
         and txn_ts - trunc(txn_ts) < numtodsinterval(11, 'hour') 
       then txn_amt else 0 end) as breakfast_sales, 
     sum (case when ( txn_ts - trunc(txn_ts) >= numtodsinterval(11, 'hour') 
         and txn_ts - trunc(txn_ts) < numtodsinterval(4, 'hour') 
       then txn_amt else 0 end) as lunch_sales, 
     sum (case when ( txn_ts - trunc(txn_ts) >= numtodsinterval(11, 'hour') 
         and txn_ts - trunc(txn_ts) < numtodsinterval(4, 'hour') 
       then txn_amt else 0 end) as dinner_sales 
    from txn_table 
group by case when txn_ts - trunc(txn_ts) > numtodsinterval(20, 'hour') 
      then trunc(txn_ts) + 1 
      else trunc(txn_ts)  
      end 

그래서 모든 영업일를 들어, 네 개의 값, 영업일의 각 세그먼트에 대한 하나 있어요. (나는 아침/점심과 점심/저녁 식사 중단 점에 대해 추측한다.)이 표를 집계하는 것은 아주 쉬워야한다.

피벗되지 않은 버전을 비롯한 다른 예는 Creating Histograms with User-Defined Buckets in the Oracle Data Warehousing Guide을 참조하십시오.

+0

이 솔루션은 우리의 재 설계에서 매우 도움이되었습니다.기본적으로 테이블의 세션 오프셋을 캡처 할 필요가 없습니다. 이것은 프로 시저 논리에서 처리 될 수 있습니다. 최종 사용자는 그것이 저장되어 있는지 상관하지 않습니다. 그럴 이유가 없다. 감사. –