2011-07-21 11 views
0

ユーザーステータスが変わるたびに、テーブルにタイムスタンプが設定されます。毎日それは "a"で始まり、いつもa→b→c→d→e→...複数の「時間の変更」を同じテーブルから追加する

私はaとbの間の合計時間を求めようとしています'と' c 'と' d 'と' e 'と' f 'の時間の加算などがあります。結果だけを追加し、その後、このselect文を複数回行うことなくこれを行う方法はあり

SELECT cast(us2.status_timestamp as date) - cast(us1.status_timestamp as date) 
FROM user_status US1, user_status US2 
WHERE US1.statID = 'a' and us2.statID = 'b' 
AND US1.user_ID = US2.user_ID 
AND US1.work_date = US2.work_date 

これは、ステータスのうちの2つの間の時間を得るために働きますか?私はより速い方法があると感じます。

注:おそらく、テーブルにLEADとLAG分析関数行ごとに

SELECT cast(status_timestamp as date) - cast(prior_status_timestamp as date) diff, 
     user_id, 
     work_date, 
     statID 
    FROM (
    SELECT status_timestamp, 
      lag(status_timestamp) over 
       (partition by user_id, 
          work_date 
       order by status_timestamp) prior_status_timestamp, 
      user_id, 
      statID, 
      work_date 
     FROM user_status) 
WHERE statID in ('b','d','f')  

を使用できるOracle

答えて

1

のためのヒキガエルを使用して、これがために前の行のステータスのタイムスタンプを取得します同じuser_idとwork_date(したがって、各日の各ユーザーの 'a'行にはprior_status_timestampがNULLになります)。現在の行とその前の行の差異を表示します。その後、適切に集計できます。

+0

私はOPが、他のすべての行セット( 'a'と 'b'、 'c'と 'd'などで、 'b'と 'c' 。 – Allan

+0

@Allan - 良い点。 'b'と 'c'、 'd'と 'e'、 'f'と 'g'の違いを除外するようにクエリを更新しました。 –

+0

しかし、あなたは "やっています" .... h、j、lなどを逃してしまった –

1

私が正しくあなたの要件を理解していれば、次のクエリは動作します:

SELECT SUM (CAST (us2.status_timestamp AS date) - CAST (us1.status_timestamp AS date)) 
FROM user_status us1, user_status us2 
WHERE CHR (ASCII (us1.statid) + 1) = us2.statid 
    AND MOD (ASCII (us1.statid), 2) <> 0 
    AND us1.user_id = us2.user_id 
    AND us1.work_date = us2.work_date; 

MOD (ASCII (us1.statid), 2)も、ASCII値と他のすべての値のために何か他のものとの文字に0を返します。 'a'は97なので、この値が0でないところから始めたいと思っています。シーケンスの次の値を得るのに非常によく似たロジックを使うことができます:文字をASCII値に変換し、1を加えてから変換します。この値をジョインで使用すると、それぞれの開始時間の対応する終了を見つけることができます。最後に、すべての違いを合計します。

0
SELECT US1.user_ID, SUM(difference) 
FROM (
SELECT US1.user_ID, cast(us2.status_timestamp as date) - cast(us1.status_timestamp as date) AS difference 
FROM user_status US1, user_status US2 
WHERE 
    ((US1.statID = 'a' and us2.statID = 'b') OR 
    (US1.statID = 'C' AND us2.statID = 'D') OR 
    (US1.statID = 'E' AND us2.statID = 'F')) 
AND US1.user_ID = US2.user_ID 
AND US1.work_date = US2.work_date 
) GROUP BY US1.user_id 
関連する問題