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

Hitung jumlah kunjungan berturut-turut

Saya melewatkan tag mysql dan menulis solusi ini. Sayangnya, ini tidak berfungsi di MySQL karena tidak mendukung fungsi jendela .

Saya tetap mempostingnya, karena saya berusaha keras. Diuji dengan PostgreSQL. Akan bekerja sama dengan Oracle atau SQL Server (atau RDBMS layak lainnya yang mendukung fungsi jendela).

Pengaturan pengujian

CREATE TEMP TABLE v(id int, visit date);
INSERT INTO v VALUES
 (444631, '2011-11-07')
,(444631, '2011-11-06')
,(444631, '2011-11-05')
,(444631, '2011-11-04')
,(444631, '2011-11-02')
,(444631, '2011-11-01')
,(444632, '2011-12-02')
,(444632, '2011-12-03')
,(444632, '2011-12-05');

Versi sederhana

-- add 1 to "difference" to get number of days of the longest period
SELECT id, max(dur) + 1 as max_consecutive_days
FROM (

   -- calculate date difference of min and max in the group
   SELECT id, grp, max(visit) - min(visit) as dur
   FROM (

      -- consecutive days end up in a group
      SELECT *, sum(step) OVER (ORDER BY id, rn) AS grp
      FROM   (

         -- step up at the start of a new group of days
         SELECT id
               ,row_number() OVER w AS rn
               ,visit
               ,CASE WHEN COALESCE(visit - lag(visit) OVER w, 1) = 1
                THEN 0 ELSE 1 END AS step
         FROM   v
         WINDOW w AS (PARTITION BY id ORDER BY visit)
         ORDER  BY 1,2
         ) x
      ) y
      GROUP BY 1,2
   ) z
GROUP  BY 1
ORDER  BY 1
LIMIT  1;

Keluaran:

   id   | max_consecutive_days
--------+----------------------
 444631 |                    4

Lebih cepat / lebih pendek

Saya kemudian menemukan cara yang lebih baik. grp jumlahnya tidak terus menerus (tetapi terus meningkat). Tidak masalah, karena itu hanya sarana untuk mencapai tujuan:

SELECT id, max(dur) + 1 AS max_consecutive_days
FROM (
    SELECT id, grp, max(visit) - min(visit) AS dur
    FROM (
      -- subtract an integer representing the number of day from the row_number()
      -- creates a "group number" (grp) for consecutive days
      SELECT id
            ,EXTRACT(epoch from visit)::int / 86400
           - row_number() OVER (PARTITION BY id ORDER BY visit) AS grp
            ,visit
      FROM   v
      ORDER  BY 1,2
      ) x
    GROUP BY 1,2
    ) y
GROUP  BY 1
ORDER  BY 1
LIMIT  1;

SQL Fiddle untuk keduanya.

Lainnya



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. MySQL LIMIT dalam Subquery Berkorelasi

  2. ALTER table - menambahkan AUTOINCREMENT di MySQL

  3. Hitung desil dari keterkinian di MySQL

  4. Kinerja beberapa sisipan MySQL

  5. PHP Kesalahan fatal:PDOException tidak tertangkap:tidak dapat menemukan driver