2016-05-10 6 views
0

動的な24時間のデータを集計するシナリオがあります。動的日付結合のためのOracleのパフォーマンスチューニング

たとえば、ユーザーがFROM日付をJan 05 2016 8:00 AMとTO dateとして選択した場合、2016年1月10日2:00 AMのデータは、2016年1月5日8:00 AMからJanに集計する必要があります06 2016 7:59 AMを1日として(2016年1月5日)

Jan 5 2016 - Jan 5 2016 8:00 AM to Jan 6 2016 7:59 AM 
Jan 6 2016 - Jan 6 2016 8:00 AM to Jan 7 2016 7:59 AM 
Jan 7 2016 - Jan 7 2016 8:00 AM to Jan 8 2016 7:59 AM 
Jan 8 2016 - Jan 8 2016 8:00 AM to Jan 9 2016 7:59 AM 
Jan 9 2016 - Jan 9 2016 8:00 AM to Jan 10 2016 2:00 AM 

これを達成するために、私はファクトテーブルの日付列から8時間を引いて、それを日付次元に結合しました。クエリは次のようになります。

SELECT D.DAY_FMT,SUM(F.MEASURE) from FACT F 
INNER JOIN DATES D ON 
to_number(to_char((F.DATESTIME - 0.3333333),'YYYYMMDD')) = D.DATEID 
WHERE F.DATESTIME between to_timestamp ('05-Jan-16 08.00.00.000000000 AM') 
and to_timestamp ('10-Jan-16 02.00.00.000000000 AM') 
GROUP BY D.DAY_FMT 

注1:時から、我々は代わりに

0.3333333(日)の0.25(日)を引くことになる6時AMある場合注2:ファクト表には数十億行があります。

上記のクエリのパフォーマンスを向上させる方法はありますか?

答えて

0

Oracleでは、日付と時刻が一緒に格納されます。あなたは平等に参加する必要はなく、どの関数内でも日付をラップする必要はありません。条件の「右側」にすべての計算が必要な場合は、必要に応じてすべての計算を行うということは、各行ごとに個別に計算するのではなく、すべての行で同じ計算を1回だけ実行することを意味します。

select f.day_fmt, sum(f.measure) as some_col_name 
from  fact f inner join dates d 
      on f.datestime >= to_date('05-Jan-16 08:00:00 AM', 'dd-Mon-yy hh:mi:ss AM') 
      and f.datestime < to_date('10-Jan-16 02:00:00 AM', 'dd-Mon-yy hh:mi:ss AM') 
group by day_fmt; 

編集:OPからさらに明確に基づいて - 列day_fmt、測定、およびdatestimeと - データが表に "事実" であると仮定します。割り当ては、day_fmtでグループ化され、ユーザーが選択した日時からユーザーが選択した日時で終わる24時間間隔でグループ化されたメジャーを集計(合計)するものです。以下の解決策。 f.datestime巻き付け関数呼び出しを使用していないことで

with user_input (sd, ed) as (
      select to_date('05-Jan-16 08:00:00 AM', 'dd-Mon-yy hh:mi:ss AM'), 
        to_date('10-Jan-16 02:00:00 AM', 'dd-Mon-yy hh:mi:ss AM') from dual 
     ), 
    prep (dt) as (
      select (select sd from user_input) + level - 1 from dual 
      connect by level < (select ed - sd from user_input) + 1 
      union 
      select ed from user_input 
     ), 
    dates (from_date, to_date) as (
      select dt, lead(dt) over (order by dt) from prep 
     ) 
select f.day_fmt, d.from_datetime, d.to_datetime, sum(f.measure) as some_column_name 
from  fact f inner join dates d 
       on f.datestime >= d.from_datetime and f.datestime < d.to_datetime 
where to_datetime is not null 
group by f.day_fmt, d.from_datetime, f.to_datetime 
order by f.day_fmt, d.from_datetime; 

、あなたは「実際」表(あなたが今作成することができますあなたがすでに持っているインデックスまたは1つのこの列に定義された索引を利用することができ、支援しますあなたの質問をスピードアップする)。

+0

ここでデータは、 1月5日2016 - 1月5日2016 8:00 AMから2016年1月6日7:59 AMに集計されません。データは、2016年1月5日〜2016年1月5日8:00 AM〜2016年1月5日11:59 PMとして集計されます。 2016年1月6日は2016年1月6日とみなされます。12AM〜1月6日2016 11:59 PM – vkr

+0

ご理解ください。あなたは何を持っていますか:テーブル内の日付と時刻(おそらく「日付」)か、ユーザーによってドロップダウンボックスから選択されていますか?いずれにしても、テーブルの開始日時と終了日時に基づいて集計する必要がある場合は、クエリのdatetimeリテラルではなく、「on」条件の右側でそれらを使用できます。 – mathguy

+0

開始日と終了日は、いくつかのドロップダウンボックスからユーザーが選択します。ユーザーがFrom DateをJan 05 2016 08:00 AMと選択すると、2016年1月5日の午前8時から午後11時59分までのデータが集計され、2016年1月6日12:00から翌日に続きますAM〜11:59 PMですが、私のここでの要件は、正確に24時間のデータ、すなわちJan 05 2016を08:00 AMから2016年1月6日午後5時59分、Jan 05 2016とJan 06 2016と08:00 AMからJan 07 2016 7:59 PMをJan 06 dataと呼び、Jan 10 2:00 AMまで続きます – vkr

関連する問題