복붙노트

[SQL] X 일 연속 확인 - 데이터베이스에 주어진 타임 스탬프를

SQL

X 일 연속 확인 - 데이터베이스에 주어진 타임 스탬프를

누군가가 나에게 당신이 데이터베이스 테이블에 X 일 연속 확인할 수있는 방법을 생각이나 힌트를 줄 수 (MySQL은) 여기에서 로그인 (사용자 ID, 타임 스탬프) 저장됩니까?

유래는 (예를 들어, 배지 매니아와 같은 - 당신은 연속 30 일 정도에 로그인 할 경우 ...) 그것을 않습니다. 어떤 기능은 당신이 사용하거나 그것을 수행하는 방법의 아이디어는 무엇인가 것인가?

login_dates 곳에서 SELECT 1 같은 뭔가 ...?

해결법

  1. ==============================

    1.다음을 사용하여이를 달성 할 수있는 변수와 함께 자기 외부 조인 시프트. 이 솔루션을 참조하십시오 :

    다음을 사용하여이를 달성 할 수있는 변수와 함께 자기 외부 조인 시프트. 이 솔루션을 참조하십시오 :

    SELECT IF(COUNT(1) > 0, 1, 0) AS has_consec
    FROM
    (
        SELECT *
        FROM
        (
            SELECT IF(b.login_date IS NULL, @val:=@val+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 또는 사용자가 연속 30 일 이상 과거에 언제든지 로그인 한 경우에 따라 0.

    이 쿼리의 기봉이 첫번째 부속 선택에 정말입니다. 우리는 더 나은 이것이 어떻게 작동하는지 이해할 수 있도록하자가 자세히 살펴 :

    다음의 예시적인 데이터 집합 :

    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:=@val+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
    

    생성합니다 :

    당신이 볼 수 있듯이, 우리가하고있는 것은 일일에 의해 조인 된 테이블을 이동하고있다. 이전 하루 연속없는 하루를 들면, NULL 값이 LEFT에 의해 생성되는 가입하세요.

    이제 비 연속적인 일이 어디 우리가 알고있는, 우리는 이동 테이블의 행이 NULL 있는지 여부를 감지하여 일 연속의 각 세트를 차별화하기 위해 변수를 사용할 수 있습니다. 그들이 NULL 경우, 일, 그래서 그냥 변수를 증가, 연속되지 않습니다. 그들이 NOT NULL 인 경우, 다음 변수를 증가하지 않습니다

    우리는 증가 변수 일 연속의 각 세트를 구분 한 후, 그 다음합니다 (consec_set 컬럼에 정의 된대로) 각각의 "설정"에 의해 그룹화하고 덜 지정된 이상이있는 세트를 필터링 HAVING 사용하는 단순한 문제입니다 연속 일 (귀하의 예제에서 30)

    그리고 마지막으로, 우리는 그 쿼리를 감싸 단순히 30 이상 일 연속 한 세트의 수를 계산합니다. 하나 이러한 세트 더 있었다 경우, 그렇지 않으면 1을 반환 0을 반환합니다.

  2. ==============================

    2.이 날짜 범위에서 별개의 (날짜) == X 인 경우 타임 스탬프의 날짜와 체크에 X를 추가 할 수 있습니다 :

    이 날짜 범위에서 별개의 (날짜) == X 인 경우 타임 스탬프의 날짜와 체크에 X를 추가 할 수 있습니다 :

    그 30 일 매일 한 번 이상 :

    SELECT distinct 1 
    FROM 
       login_dates l1 
    inner join
       login_dates l2
          on l1.user = l2.user and 
             l2.timestamp between l1.timestamp and  
                                  date_add( l1.timestamp, Interval X day )
    where l1.user = some_user
    group by 
       DATE(l1.timestamp)
    having 
       count( distinct DATE(l1.timestamp) ) = X
    

    (당신은 ... 성능 요구 사항에 대해 말하지 않는다;))

    * 편집 ~ 만 지난 X 일에 대한 쿼리 : 동쪽 그 30 일마다 하루에 한 번

    SELECT distinct 1 
    FROM 
       login_dates l1 
    where l1.user = some_user
          and l1.timestamp >  date_add( CURDATE() , Interval -X day )
    group by
        l1.user
    having 
       count( distinct DATE(l1.timestamp) ) = X
    
  3. ==============================

    3.그것만으로도 SQL로 해결하기 어려운 문제입니다.

    그것만으로도 SQL로 해결하기 어려운 문제입니다.

    문제의 핵심은 하나 개의 쿼리에서 서로 동적 결과 세트를 비교해야한다는 것입니다. 예를 들어, 다음, 하나 DATE에 대한 모든 로그인 / 세션 ID를 얻을 수 (당신이 결정하는 DATE_ADD를 사용할 수 있습니다) 날짜 ()에서 로그인의 그룹에 목록을 JOIN 또는 UNION해야합니다. 당신은 연속 날짜의 N 번호를이 작업을 수행 할 수 있습니다. 당신이 어떤 행이 남아있는 경우, 그 세션은 그 기간에 기록되어있다.

    다음 표를 가정합니다 :

    세션 id INT, 만든 날짜

    모든이 쿼리 반환이 지난 이틀 동안 열을 가지고있는 세션 id :

    select t1.sessionid from logins t1 
      join logins t2 on t1.sessionid=t2.sessionid 
      where t1.created = DATE(date_sub(now(), interval 2 day)) 
        AND t2.created = DATE(date_sub(now(), interval 1 day));
    

    당신이 볼 수 있듯이, SQL은 30 일 동안 밥맛 얻을 것이다. 스크립트를 생성해야합니다. :-디

    이것은 더 매일이, 로그인 테이블이 세션으로 업데이트되어 있다고 가정합니다.

    이 실제로 문제가 해결되는지 모르겠지만, 나는 프레임에게 문제를 도움이되기를 바랍니다.

    행운을 빕니다.

  4. ==============================

    4.이 기본값 1. login_dates 테이블에 여분의 열 consecutive_days이 더 간단하지 않을까요이 그 날에 끝나는 연속 날짜의 길이를 나타냅니다.

    이 기본값 1. login_dates 테이블에 여분의 열 consecutive_days이 더 간단하지 않을까요이 그 날에 끝나는 연속 날짜의 길이를 나타냅니다.

    이전 일에 대한 항목이 있는지 확인 어디 login_dates에 트리거 후 삽입을 만들 수 있습니다.

    존재하지 않는 경우는, 다음 필드는 새로운 순서는 날짜에 시작하는 기본 값 1 의미를 가질 것이다.

    여기하다면 이전의 일에 대한 항목이 다음 그 전날의 다음으로 기본 1 일 개 더를 days_logged_in 값을 변경합니다.

    전의:

    | date       | consecutive_days |
    |------------|------------------|
    | 2013-11-13 | 5                |
    | 2013-11-14 | 6                |
    | 2013-11-16 | 1                |
    | 2013-11-17 | 2                |
    | 2013-11-18 | 3                |
    
  5. from https://stackoverflow.com/questions/11539065/check-for-x-consecutive-days-given-timestamps-in-database by cc-by-sa and MIT license