1

MySQL を使用して、特定のコードの過去 30 分以内の 5 分間に 4 つのエントリがあったかどうかを調べたいと考えています。

    name     stamp                 code
    a        2013-02-03 13:12:01   red
    b        2013-02-03 13:23:01   red
    c        2013-02-03 13:23:11   red
    d        2013-02-03 13:24:01   green
    e        2013-02-03 13:24:05   red
    f        2013-02-03 13:24:21   red
    g        2013-02-03 13:25:01   red
    h        2013-02-03 13:48:01   red

したがって、2013-02-03 13:50:00 にクエリを実行すると、過去 30 分間に 5 分間のブロック内に 4 つ以上のエントリのグループがあったエントリの数が返されます最初に一致したエントリのスタンプ。ただし、コードレッドのエントリのみ。

このサンプル テーブルを使用した結果は次のようになります: 5, 2013-02-03 13:23:01

単一のクエリで可能ですか? ありがとう!

編集: このクエリに問題はありますか?

    SELECT COUNT(*), rolling.stamp
    FROM mytable thisrow JOIN mytable rolling 
       ON (thisrow.stamp BETWEEN rolling.stamp AND 
              rolling.stamp + INTERVAL 5 MINUTE)
    WHERE rolling.stamp >= DATE_SUB(NOW(), INTERVAL 30 MINUTE)
      AND code = 'red'
    GROUP BY 2 HAVING COUNT(*) >= 4

上記のテーブルに対して実行すると、目的の「5、2013-02-03 13:23:01」が得られます。

PS I は、この例の now() を '2013-02-03 13:50:00' に置き換えました

4

1 に答える 1

0

GROUP BYはい、 aと aで可能です。丸め (から減算) をHAVING使用して、300 秒 (5 分) のブロックにグループ化します。UNIX_TIMESTAMPstamp % 300stamp

SELECT COUNT(*), MIN(stamp)
FROM mytable
WHERE stamp >= NOW() - INTERVAL 30 minute
GROUP BY 
    FROM_UNIXTIME(
       UNIX_TIMESTAMP(stamp) - 
       MOD(UNIX_TIMESTAMP(stamp),300)
    )
HAVING COUNT(*) >= 4

これは、ローリング ブロックではなくクロック ブロックを意味していると想定しています。これにより、「30 分前」ルールに問題が生じるため、少し慎重に検討する必要があります。

編集:あなたがそれをローリングブロックにすることを主張したのを見て...いくつかのおいしいひどいパフォーマンスの結合を追加しましょう。

SELECT COUNT(*), rolling.stamp
FROM mytable thisrow JOIN mytable rolling 
   ON (thisrow.stamp BETWEEN rolling.stamp AND 
          rolling.stamp + INTERVAL 5 MINUTE)
WHERE rolling.stamp >= NOW() - INTERVAL 30 minute
GROUP BY 2 HAVING COUNT(*) >= 4; 

インデックスがある場合はパフォーマンスが向上しますが、これは事実上、 n ² 行 ( nは行数)でstampフィルタリングしている恐ろしい、恐ろしいパフォーマンスのクロス結合です。これを大きなテーブルで実行しないでください。

于 2013-09-09T17:11:24.837 に答える