7

私の質問は、連続するイベント間の平均時間を計算する SQL クエリを作成する方法についてです。

私は小さなテーブルを持っています:

event Name    |    Time

stage 1       |    10:01
stage 2       |    10:03
stage 3       |    10:06
stage 1       |    10:10
stage 2       |    10:15
stage 3       |    10:21
stage 1       |    10:22
stage 2       |    10:23
stage 3       |    10:29

ステージ (i) とステージ (i+1) の間の時間の平均を回答として取得するクエリを作成したいと考えています。

たとえば、ステージ 2 とステージ 3 の間の平均時間は 5 です。

(3+6+6)/3 =  5
4

8 に答える 8

15

ああ、そして黒魔術をまぶして:

select a.eventName, b.eventName, AVG(DATEDIFF(MINUTE, a.[Time], b.[Time])) as Average from
     (select *, row_number() over (order by [time]) rn from events) a
join (select *, row_number() over (order by [time]) rn from events) b on (a.rn=b.rn-1)
group by
a.eventName, b.eventName

これにより、次のような行が得られます。

stage3  stage1  2
stage1  stage2  2
stage2  stage3  5

最初の列は開始イベント、2 番目の列は終了イベントです。イベント 1 の直後にイベント 3 がある場合は、それもリストされます。それ以外の場合は、どの段階がどの段階に続くかについていくつかの基準を提供する必要があるため、時間はそれらの間でのみ計算されます。

追加:これは、Transact-SQL (MSSQL、Sybase) と PL/SQL (Oracle、PostgreSQL) の両方で問題なく動作するはずです。ただし、テストしていないため、構文エラーが発生する可能性があります。これは、MySQL のどのエディションでも機能しません。

于 2009-12-22T15:30:34.023 に答える
2
Select Avg(differ) from (
 Select s1.r, s2.r, s2.time - s1.time as differ from (
 Select * From (Select rownum as r, inn.time from table inn order by time) s1
 Join (Select rownum as r, inn.time from table inn order by time) s2
 On mod(s2.r, 3) = 2 and s2.r = s1.r + 1
 Where mod(s1.r, 3) = 1)
);

ステージ数の変化に合わせてパラメータを変更することができます。これは現在、3 段階のプロセスから段階 1 と 2 の間の平均を見つけるように設定されています。

いくつかのタイプミスを編集

于 2009-12-22T15:24:42.533 に答える
1

答えが必要なSQLのフレーバーはわかりません。これはおそらく、SQL Serverのコードが必要であることを意味します(SOタグの使用法では[sql]は一般的に[sql-server]として)。

ただし、あなた(または将来のシーカー)がOracleを使用している場合に備えて、この種のクエリは、この場合は分析関数を使用すると非常に簡単LAG()です。見てみな:

SQL> select stage_range
  2         , avg(time_diff)/60 as average_time_diff_in_min
  3  from
  4      (
  5          select event_name
  6                 , case when event_name = 'stage 2' then  'stage 1 to 2'
  7                      when event_name = 'stage 3' then  'stage 2 to 3'
  8                      else  '!!!' end as stage_range
  9                 , stage_secs - lag(stage_secs)
 10                              over (order by ts, event_name) as time_diff
 11                 from
 12                     ( select event_name
 13                              , ts
 14                              , to_number(to_char(ts, 'sssss')) as stage_secs
 15                       from timings )
 16      )
 17         where event_name in ('stage 2','stage 3')
 18  group by stage_range
 19  /

STAGE_RANGE  AVERAGE_TIME_DIFF_IN_MIN
------------ ------------------------
stage 1 to 2               2.66666667
stage 2 to 3                        5

SQL>

TIME列をDATEデータ型として格納しているため、内部クエリの形式を変更する必要があります。そのため、数学を明確にするために秒に変換します。別の解決策は、Day to Second Interval代わりにデータ型を使用することです。しかし、この解決策は本当にすべてですLAG()

編集

このクエリに対する私の見解では、前のステージ3と次のステージ1の差を明示的に計算していません。これは要件の問題です。

于 2009-12-22T16:15:12.493 に答える
1

テーブルのデザインに欠陥があります。どのステージ 1 がどのステージ 2 に対応するかをどのように判断できますか? これを行う方法がなければ、あなたのクエリは不可能だと思います。

于 2009-12-22T15:05:56.627 に答える
1

最も簡単な方法は、時間順に並べ替え、カーソル (tsql) を使用してデータを反復処理することです。カーソルは悪であるため、時間順に並べられたデータをアプリケーション コードにフェッチし、そこで反復することをお勧めします。SQL でこれを行う方法はおそらく他にもありますが、それらは非常に複雑で、非標準の言語拡張に依存します。

于 2009-12-22T15:07:54.720 に答える
0
WITH    q AS
        (
        SELECT  'stage 1' AS eventname, CAST('2009-01-01 10:01:00' AS DATETIME) AS eventtime
        UNION ALL
        SELECT  'stage 2' AS eventname, CAST('2009-01-01 10:03:00' AS DATETIME) AS eventtime
        UNION ALL
        SELECT  'stage 3' AS eventname, CAST('2009-01-01 10:06:00' AS DATETIME) AS eventtime
        UNION ALL
        SELECT  'stage 1' AS eventname, CAST('2009-01-01 10:10:00' AS DATETIME) AS eventtime
        UNION ALL
        SELECT  'stage 2' AS eventname, CAST('2009-01-01 10:15:00' AS DATETIME) AS eventtime
        UNION ALL
        SELECT  'stage 3' AS eventname, CAST('2009-01-01 10:21:00' AS DATETIME) AS eventtime
        UNION ALL
        SELECT  'stage 1' AS eventname, CAST('2009-01-01 10:22:00' AS DATETIME) AS eventtime
        UNION ALL
        SELECT  'stage 2' AS eventname, CAST('2009-01-01 10:23:00' AS DATETIME) AS eventtime
        UNION ALL
        SELECT  'stage 3' AS eventname, CAST('2009-01-01 10:29:00' AS DATETIME) AS eventtime
        )
SELECT  (
        SELECT  AVG(DATEDIFF(minute, '2009-01-01', eventtime))
        FROM    q
        WHERE   eventname = 'stage 3'
        ) - 
        (
        SELECT  AVG(DATEDIFF(minute, '2009-01-01', eventtime))
        FROM    q
        WHERE   eventname = 'stage 2'
        )

これは、ステージの完全なグループが常にあり、それらが常に同じ順序で進むという事実に依存しています (つまり、stage 1then )stage 2stage 3

于 2009-12-22T15:21:19.940 に答える
0

これを試して

   Select Avg(e.Time - s.Time)
   From Table s
     Join Table e 
         On e.Time = 
             (Select Min(Time)
              From Table
              Where eventname = s.eventname 
                 And time > s.Time)
         And Not Exists 
             (Select * From Table
              Where eventname = s.eventname 
                 And time < s.Time)

ステージの開始を表す各レコードについて、この sql はそれを終了を表すレコードに結合し、終了時刻と開始時刻の差を取り、それらの差を平均します。Not Exists は、終了レコードに結合された開始レコードの中間結果セットに開始レコードのみが含まれることを保証します...そして最初の結合条件は、1 つの終了レコード (同じ名前と後の次の時間値を持つもの) のみを保証します。開始時間) がそれに結合されます...

結合後、平均を取る前の中間結果セットを表示するには、次のコマンドを実行します。

   Select s.EventName,
       s.Time Startime, e.Time EndTime, 
       (e.Time - s.Time) Elapsed
   From Table s
     Join Table e 
         On e.Time = 
             (Select Min(Time)
              From Table
              Where eventname = s.eventname 
                 And time > s.Time)
         And Not Exists 
             (Select * From Table
              Where eventname = s.eventname 
                 And time < s.Time)
于 2009-12-22T15:17:42.140 に答える
0

コメントはできませんが、HLGEM に同意せざるを得ません。提供されたデータ セットで判断できますが、OP は、一度に存在する単一のステージ セットのみに依存するのは楽観的すぎる可能性があることを認識する必要があります。


event Name    |    Time

stage 1       |    10:01
stage 2       |    10:03
stage 3       |    10:06
stage 1       |    10:10
stage 2       |    10:15
stage 3       |    10:21
stage 1       |    10:22
stage 2       |    10:23
stage 1       |    10:25     --- new stage 1
stage 2       |    10:28     --- new stage 2
stage 3       |    10:29
stage 3       |    10:34     --- new stage 3

環境やデータを作成しているものはわかりません。テーブルが正しく構築されているかどうかを判断するのは OP 次第です。

Oracle はこれを Analytics で処理します。Vilxの答えのように。

于 2009-12-22T15:38:35.780 に答える