Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Periksa x hari berturut-turut - stempel waktu yang diberikan dalam basis data

Anda dapat melakukannya dengan menggunakan shift self-outer-join dalam hubungannya dengan variabel. Lihat solusi ini:

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

Ini akan mengembalikan 1 atau 0 berdasarkan apakah pengguna telah masuk selama 30 hari berturut-turut atau lebih pada KAPAN SAJA di masa lalu.

Beban dari kueri ini benar-benar ada di subpilihan pertama. Mari kita lihat lebih dekat agar kita dapat lebih memahami cara kerjanya:

Dengan kumpulan data contoh berikut:

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');

Kueri ini:

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

Akan menghasilkan:

Seperti yang Anda lihat, apa yang kami lakukan adalah bergeser tabel bergabung dengan +1 hari. Untuk setiap hari yang tidak berurutan dengan hari sebelumnya, NULL nilai dihasilkan oleh LEFT JOIN.

Sekarang kita tahu di mana hari yang tidak berurutan, kita dapat menggunakan variabel untuk membedakan setiap set hari berturut-turut dengan mendeteksi apakah baris tabel yang digeser adalah NULL . Jika mereka NULL , hari-harinya tidak berurutan, jadi tambahkan saja variabelnya. Jika mereka NOT NULL , maka jangan tambahkan variabel:

Setelah kita membedakan setiap rangkaian hari berturut-turut dengan variabel kenaikan, selanjutnya tinggal mengelompokkan berdasarkan setiap "set" (sebagaimana didefinisikan dalam consec_set kolom) dan menggunakan HAVING untuk memfilter set apa pun yang memiliki kurang dari hari berturut-turut yang ditentukan (30 dalam contoh Anda):

Lalu akhirnya, kita bungkus ITU kueri dan cukup hitung jumlah set yang memiliki 30 hari berturut-turut atau lebih. Jika ada satu atau lebih dari kumpulan ini, kembalikan 1 , jika tidak, kembalikan 0 .

Lihat demo langkah demi langkah SQLFiddle



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. mysqli atau mati, apakah harus mati?

  2. Aktifkan Python untuk Terhubung ke MySQL melalui SSH Tunneling

  3. Kesalahan MySql:1364 Bidang 'display_name' tidak memiliki nilai default

  4. Memilih semua kolom yang dimulai dengan XXX menggunakan karakter pengganti?

  5. MAKEDATE() Contoh – MySQL