sql >> データベース >  >> RDS >> Mysql

x日連続でチェック-データベースにタイムスタンプを指定

    これは、シフトされた自己外部結合を変数と組み合わせて使用​​して実現できます。このソリューションを参照してください:

    SELECT IF(COUNT(1) > 0, 1, 0) AS has_consec
    FROM
    (
        SELECT *
        FROM
        (
            SELECT IF(b.login_date IS NULL, @val:[email protected]+1, @val) AS consec_set
            FROM tbl a
            CROSS JOIN (SELECT @val:=0) var_init
            LEFT JOIN tbl b ON 
                a.user_id = b.user_id AND
                a.login_date = b.login_date + INTERVAL 1 DAY
            WHERE a.user_id = 1
        ) a
        GROUP BY a.consec_set
        HAVING COUNT(1) >= 30
    ) a
    

    これにより、1のいずれかが返されます または0 ユーザーがいつでもに30日以上連続してログインしたかどうかに基づきます 過去に。

    このクエリの矢面に立つのは、実際には最初の副選択です。これがどのように機能するかをよりよく理解できるように、詳しく見てみましょう。

    次のデータセットの例:

    CREATE TABLE tbl (
      user_id INT,
      login_date DATE
    );
    
    INSERT INTO tbl VALUES
    (1, '2012-04-01'),  (2, '2012-04-02'),
    (1, '2012-04-25'),  (2, '2012-04-03'),
    (1, '2012-05-03'),  (2, '2012-04-04'),
    (1, '2012-05-04'),  (2, '2012-05-04'),
    (1, '2012-05-05'),  (2, '2012-05-06'),
    (1, '2012-05-06'),  (2, '2012-05-08'),
    (1, '2012-05-07'),  (2, '2012-05-09'),
    (1, '2012-05-09'),  (2, '2012-05-11'),
    (1, '2012-05-10'),  (2, '2012-05-17'),
    (1, '2012-05-11'),  (2, '2012-05-18'),
    (1, '2012-05-12'),  (2, '2012-05-19'),
    (1, '2012-05-16'),  (2, '2012-05-20'),
    (1, '2012-05-19'),  (2, '2012-05-21'),
    (1, '2012-05-20'),  (2, '2012-05-22'),
    (1, '2012-05-21'),  (2, '2012-05-25'),
    (1, '2012-05-22'),  (2, '2012-05-26'),
    (1, '2012-05-25'),  (2, '2012-05-27'),
                        (2, '2012-05-28'),
                        (2, '2012-05-29'),
                        (2, '2012-05-30'),
                        (2, '2012-05-31'),
                        (2, '2012-06-01'),
                        (2, '2012-06-02');
    

    このクエリ:

    SELECT a.*, b.*, IF(b.login_date IS NULL, @val:[email protected]+1, @val) AS consec_set
    FROM tbl a
    CROSS JOIN (SELECT @val:=0) var_init
    LEFT JOIN tbl b ON 
        a.user_id = b.user_id AND
        a.login_date = b.login_date + INTERVAL 1 DAY
    WHERE a.user_id = 1
    

    生成されます:

    ご覧のとおり、私たちが行っているのはシフトです。 +1日までに参加したテーブル。前日と連続していない日ごとに、NULL 値はLEFTJOINによって生成されます。

    わかった 連続していない日がある場合は、変数を使用して各セットを区別できます。 シフトされたテーブルの行がNULLであるかどうかを検出することにより、連続する日の数 。 NULLの場合 、日は連続していないため、変数をインクリメントするだけです。 NOT NULLの場合 、次に変数をインクリメントしないでください:

    増分変数を使用して連続する日の各セットを区別した後は、(consec_setで定義されているように)各「セット」ごとにグループ化するだけです。 列)およびHAVINGを使用します 指定された連続日数(この例では30日)未満のセットを除外するには:

    そして最後に、それをラップします クエリを実行し、30日以上連続したセットの数を単純にカウントします。これらのセットが1つ以上あった場合は、1を返します。 、それ以外の場合は0を返します 。

    SQLFiddleのステップバイステップデモ をご覧ください。



    1. 区切り文字に基づくT-SQL分割文字列

    2. MySQLとMariaDBのセキュリティを実現するための10のヒント

    3. MariaDBとは何ですか? MariaDBはどのように機能しますか?

    4. SQLiteException:テーブルはすでに存在します