6

私は次の構造のSQLiteデータベースを持っています:

rowid       ID                  startTimestamp   endTimestamp   subject
1           00:50:c2:63:10:1a   1000             1090           entrance
2           00:50:c2:63:10:1a   1100             1270           entrance
3           00:50:c2:63:10:1a   1300             1310           door1
4           00:50:c2:63:10:1a   1370             1400           entrance
.
.
.

ここでsqlfiddleを準備しました:http ://sqlfiddle.com/#!2/fe8c6 / 2

このSQLクエリを使用すると、1つの行と次の行の間のendTimeとstartTimeの平均差を、件名とIDで並べ替えて取得できます。

SELECT
    id,
    ( MAX(endtimestamp) - MIN(startTimestamp)
    - SUM(endtimestamp-startTimestamp)
    ) / (COUNT(*)-1) AS averageDifference
FROM
    table1
WHERE ID = '00:50:c2:63:10:1a'
AND subject = 'entrance'
GROUP BY id;

私の問題:平均値を計算することは問題ありません、それはこのクエリを行います。しかし、どうすればこの値の標準偏差と分散を取得できますか?

4

3 に答える 3

3

最初に、テーブルをそれ自体に結合し、IDでグループ化することにより、関心のある時間差を見つけ、次に、平均、分散を次のようV(x) = E(x^2) - (E(x))^2に、標準偏差を次のように見つけsqrt(V)ます。

SELECT ID, AVG(diff) AS average,
       AVG(diff*diff) - AVG(diff)*AVG(diff) AS variance,
       SQRT(AVG(diff*diff) - AVG(diff)*AVG(diff)) AS stdev
FROM
    (SELECT t1.id, t1.endTimestamp,
            min(t2.startTimeStamp) - t1.endTimestamp AS diff
    FROM table1 t1
    INNER JOIN table1 t2
    ON t2.ID = t1.ID AND t2.subject = t1.subject
    AND t2.startTimestamp > t1.startTimestamp  -- consider only later startTimestamps
    WHERE t1.subject = 'entrance'
    GROUP BY t1.id, t1.endTimestamp) AS diffs
GROUP BY ID
于 2013-01-20T21:21:04.040 に答える
3

単純な合計よりも複雑な数式の場合、次のように、対応する次の開始時刻を調べて、各レコードの実際の差の値を計算する必要があります。

SELECT (SELECT MIN(startTimestamp)
        FROM table1 AS next
        WHERE next.startTimestamp > table1.startTimestamp
          AND ID = '...'
       ) - endTimestamp AS timeDifference
FROM table1
WHERE nextStartTimestamp IS NOT NULL
  AND ID = '...'

次に、すべての差の値を使用して計算を行うことができます。

SELECT SUM(timeDifference) / COUNT(*) AS average,
       AVG(timeDifference)            AS moreEfficientAverage,
       SUM(timeDifference * timeDifference) / COUNT(*) -
       AVG(timeDifference) * AVG(timeDifference) AS variance
FROM (SELECT (SELECT MIN(startTimestamp)
              FROM table1 AS next
              WHERE next.startTimestamp > table1.startTimestamp
                AND next.ID = '...'
             ) - endTimestamp AS timeDifference
      FROM table1
      WHERE nextStartTimestamp IS NOT NULL
        AND ID = '...')
于 2013-01-20T20:53:01.757 に答える
1

ポイントの数:

  1. 平均の式が間違っています。正しい式はSUM(endtimestamp-starttimestamp)/COUNT(endtimestamp)です。なぜあなたがMIN/MAX用語を持っているのか分かりません。COUNT(*)行をカウントNULLし、間違った結果を返します。
  2. SQLliteにはavg、平均を求める関数があります。
  3. 分散の式は次のとおりです。SUM((endtimestamp-starttimestamp)*(endtimestamp-starttimestamp)) - AVG(endtimestamp-starttimestamp)*AVG(endtimestamp-starttimestamp)
  4. 標準偏差は分散の平方根です。

質問の作成者のコメントに応えて、分散を計算するには、開始時間と終了時間を自己結合によって互いにペアにする必要があります。

SQL liteにrow_number関数がないため、これは少しエレガントではありません。

SELECT id,
       AVG(startTimestamp-endTimestamp) as mean,
       SUM((startTimestamp-endTimestamp)^2) - AVG(startTimestamp-endTimestamp)^2 as variance,
       SQRT(SUM((startTimestamp-endTimestamp)^2) - AVG(startTimestamp-endTimestamp)^2) as stDev
FROM
    (SELECT
        t1.id,
        t1.endTimestamp,
        MIN(t2.startTimestamp) as starttimestamp
    FROM table1 t1
         INNER JOIN
         table1 t2 ON t1.endTimestamp<=t2.startTimestamp
    GROUP BY t1.id, t1.endTimestamp) t
GROUP BY id;

SQLフィドルを参照してください

于 2013-01-20T20:58:37.330 に答える