3

次の列を持つテーブルがあります。

SESSION_ID      USER_ID          CONNECT_TS
--------------  ---------------  ---------------
1               99               2013-01-01 2:23:33
2               101              2013-01-01 2:23:55
3               104              2013-01-01 2:24:41
4               101              2013-01-01 2:24:43
5               233              2013-01-01 2:25:01

毎日のユーザー数、過去 45 日間にアプリケーションを使用したユーザーとして定義される「アクティブ ユーザー」の数を取得する必要があります。これが私たちが思いついたものですが、もっと良い方法が必要だと感じています:

select trunc(a.connect_ts)
, count(distinct a.user_id) daily_users
, count(distinct b.user_id) active_users
from sessions a
  join sessions b
    on (b.connect_ts between trunc(a.connect_ts) - 45 and trunc(a.connect_ts))
where a.connect_ts between '01-jan-13' and '12-jun-13'
  and b.connect_ts between '01-nov-12' and '12-jun-13'
group by trunc(a.connect_ts);

ウィンドウ関数を調べましたが、個別のカウントがサポートされているようには見えません。また、最初に集計を一時テーブルにロードすることも検討しましたが、ここでも個別のカウントが除外されました。これを行うためのより良い方法はありますか?

4

2 に答える 2

0

最初に行うことは、興味のある日のリストを生成することです。

select (trunc(sysdate, 'yyyy') -1) + level as ts_day
from dual
connect by level <= to_number( to_char(sysdate, 'DDD' ) )

これにより、今年の 01-JAN から今日までの日付のテーブルが生成されます。テーブルをこのサブクエリに結合します。クロス結合の使用は、範囲内のデータ量によっては特に効率的ではない場合があります。したがって、これを概念実証と見なし、必要に応じて調整してください。

with days as
 ( select (trunc(sysdate, 'yyyy') -1) + level as ts_day
   from dual
   connect by level <= to_number( to_char(sysdate, 'DDD' ) ) )
select days.ts_day
       , sum ( case when trunc(connect_ts) = ts_day then 1 else 0 end ) as daily_users
       , sum ( case when trunc(connect_ts) between ts_day - 45 and ts_day then 1 else 0 end ) as active_users
from days
     cross join sessions  
where connect_ts between trunc(sysdate, 'yyyy') - 45 and sysdate
group by ts_day
order by ts_day
/
于 2013-06-14T03:18:51.607 に答える