Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Sprawdź x kolejnych dni - podane znaczniki czasu w bazie danych

Możesz to osiągnąć za pomocą przesuniętego sprzężenia zewnętrznego w połączeniu ze zmienną. Zobacz to rozwiązanie:

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

To zwróci albo 1 lub 0 na podstawie tego, czy użytkownik logował się przez 30 kolejnych dni lub dłużej o KAŻDEJ CZASO w przeszłości.

Cel tego zapytania leży w pierwszej podselekcji. Przyjrzyjmy się bliżej, abyśmy mogli lepiej zrozumieć, jak to działa:

Z następującym przykładowym zestawem danych:

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

To zapytanie:

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

Wyprodukuje:

Jak widać, to, co robimy, to przesuwanie dołączył stół o +1 dzień. Dla każdego dnia, który nie jest następujący po dniu poprzednim, NULL wartość jest generowana przez LEFT JOIN.

Teraz, gdy wiemy tam, gdzie są dni nie następujące po sobie, możemy użyć zmiennej do rozróżnienia każdego zestawu kolejnych dni, wykrywając, czy przesunięte wiersze tabeli są NULL . Jeśli są NULL , dni nie następują po sobie, więc po prostu zwiększ zmienną. Jeśli są NOT NULL , nie zwiększaj wartości zmiennej:

Po rozróżnieniu każdego zestawu kolejnych dni za pomocą zmiennej inkrementacyjnej, wystarczy po prostu grupować według każdego „zestawu” (zgodnie z definicją w consec_set kolumna) i przy użyciu HAVING aby odfiltrować dowolny zestaw, który ma mniej niż określone kolejne dni (30 w twoim przykładzie):

W końcu zapakujemy TO zapytanie i po prostu policz liczbę zestawów, które miały 30 lub więcej kolejnych dni. Jeśli był jeden lub więcej z tych zestawów, zwróć 1 , w przeciwnym razie zwróć 0 .

Zobacz prezentację SQLFiddle krok po kroku



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Migracja bazy danych MySQL z CloudSQL do AWS RDS

  2. Jak tworzyć relacje w MySQL

  3. Funkcja MySQL LOG2() – Zwróć logarytm Base-2 wartości

  4. Wybierz dane z zakresu dat/czasów

  5. Połącz się ze zdalnym serwerem MySQL za pomocą SSL z PHP