2010-03-18 4 views
3

SQLite 데이터베이스에서 통계 기반 응용 프로그램을 작성하고 있습니다. 사용자 로그인 및 로그 아웃 (SessionStart, SessionEnd DateTimes)을 기록하는 테이블이 있습니다.SQL 쿼리 : 두 개의 DateTime 타임 스탬프가 주어진 경우 "N 시간 동안 보았습니다"를 확인하는 방법?

사용자가 의 시간대가 인 시간을 표시 할 수있는 검색어입니다. 선 그래프 방식으로 일종의 12:00와 1:00 AM 사이에 60 명의 사용자가 로그인했습니다. (어느 시점에서든) 1시와 2시 사이에 로그인 한 사용자가 54 명이었습니다.

그리고 저는이 이유를 설명 할 수 있기를 바랍니다. 나는 레코드를 .NET으로 가져올 수 없으며 그렇게 반복 할 수 없다.

나는이 접근법이 느리고 느린 것으로 판명되었지만 다소 시간이 많이 걸리는 접근 방식, 즉 시간별 하위 쿼리를 제안했습니다. 나는 두 개의 날짜 시간이 특정 시간을 durring 볼 된 경우 (최상의 시나리오 결정하는 무슨 더 나은 방법이 궁금하네요

SELECT 
     case 
     when (strftime('%s',datetime(date(sessionstart), '+0 hours')) > strftime('%s',sessionstart) 
     AND strftime('%s',datetime(date(sessionstart), '+0 hours')) < strftime('%s',sessionend)) 
     OR (strftime('%s',datetime(date(sessionstart), '+1 hours')) > strftime('%s',sessionstart) 
     AND strftime('%s',datetime(date(sessionstart), '+1 hours')) < strftime('%s',sessionend)) 
     OR (strftime('%s',datetime(date(sessionstart), '+0 hours')) < strftime('%s',sessionstart) 
     AND strftime('%s',datetime(date(sessionstart), '+1 hours')) > strftime('%s',sessionend)) 
     then 1 else 0 end as hour_zero, 
... hour_one, 
... hour_two, 
........ hour_twentythree 
FROM UserSession 

.. 순식간에 몇 십만 기록이를 계산 할 수 있어야합니다 여러 날에 기록되었지만 필요하지 않은 경우 시간이 몇 번 엇갈 렸습니까?

내가 가진 다른 유일한 아이디어는이 "시간"테이블을 가지고 있으며 사용자가 런타임에 보았던 시간을 계산하는 것입니다. 그러나 이것은 이전 SQL보다 더 많은 해킹 인 것처럼 느낍니다.

도움이 될 것입니다.

+0

DATE 부분을 전혀 신경 쓰지 않습니까? 전체 기록, 일부 날짜 범위 또는 매일 별도로 매시간 집계가 필요합니까? – van

+0

날짜 부분을 잘라내는 유일한 문제는 1 일 이상 로그인 할 수있는 사용자가 있기 때문에 25 시간 세션 동안 추가 시간을 고려하는 것이 가장 좋은 경우입니다. 특정 사용자에 대해 매시간 또는 테이블의 다른 식별자를 집계 할 것입니다. 이것은 몇 십만 회의 세션을 포함 할 수 있습니다. – efess

답변

1

아마도 로그 아웃 시간이 기록 될 때 사용자가 로그인 한 시간을 결정하기 위해 레코드를 채우는 다른 테이블을 가질 수 있습니까? 예를

create table hourlyUseLog (
    userID text not null, 
    date float, // julian Day 
    hour0 integer default 0, 
    hour1 integer default 0, 

etc... 

    hour23 integer default 0, 
); 

를 들어

이 같은 구조를 가지고 있다면, 당신은 주어진 시간/날짜에 기록 된 (또는 다수의 사용자가 로그인 한 방법) 사람의 매우 빠른 쿼리를 할 수 있습니다.

또한 SQLite는 비트 필드와 비트 연산을 지원하므로 하루 동안의 모든 시간을 단일 정수로 나타내고 사용자가 활성화 된 시간에 따라 비트를 뒤집을 수도 있습니다. 이렇게하면 비트 마스크를 사용하여보다 빠른 쿼리를 수행 할 수 있으며 시간을 줄리아 언 (시간 부분 만) 표현으로 변환하거나 비트 계산 루틴을 사용하여 시스템에서 소비 한 시간을 계산하는 메커니즘을 제공합니다.

또한 실시간 활동보고가 필요하고 시스템에 로그인 한 사용자를 중앙 집중식으로 표시 할 수있는 경우 hourlyUseLog 레코드를 업데이트하는 시간별 배치 프로세스를 실행할 수 있습니다.

+0

이것이 최선의 방법이라고 생각합니다. 마틴의 답변은 내 것보다 훨씬 깔끔하지만, 내 것과 동일한 And/Or 작업을 수행하며 속도가 느립니다. 이 경로는 가장 좋은 해결책이라고 생각합니다. 시간별 로그 또는 롤업 테이블입니다. 감사합니다. – efess

1

나는 "해킹"아이디어와 함께 갈 것이지만 실제로는 해킹이라고 생각하지 않습니다. 시간이 끝난 후에도 가치는 변하지 않을 것입니다. 그래서 한번 계산하지 마시고 그것? 롤업 테이블은 이에 적합하며 추적중인 사용자 수에 관계없이 일관된 쿼리 시간을 제공합니다.

매 시간마다 계산하거나 로그인/로그 아웃 이벤트에서 각 시간의 카운터를 증가시키고 예약 된 작업을 피할 수 있습니다.

2

Sybase (T-SQL dialect)에서 약간만 재생되어이 쿼리가 나왔습니다.

SELECT 
    StartHour AS Hour, COUNT(*) AS SessionCount 
FROM 
    (SELECT 
     CONVERT(DATETIME, '2001-01-01 ' + Hour + ':00:00') as StartHour, 
     DATEADD(HH, 1, CONVERT(DATETIME, '2001-01-01 ' + Hour + ':00:00')) as EndHour 
    FROM 
     (SELECT '00' AS Hour UNION ALL SELECT '01' AS Hour UNION ALL 
     SELECT '02' AS Hour UNION ALL SELECT '03' AS Hour UNION ALL 
     SELECT '04' AS Hour UNION ALL SELECT '05' AS Hour UNION ALL 
     SELECT '06' AS Hour UNION ALL SELECT '07' AS Hour UNION ALL 
     SELECT '08' AS Hour UNION ALL SELECT '09' AS Hour UNION ALL 
     SELECT '10' AS Hour UNION ALL SELECT '11' AS Hour UNION ALL 
     SELECT '12' AS Hour UNION ALL SELECT '13' AS Hour UNION ALL 
     SELECT '14' AS Hour UNION ALL SELECT '15' AS Hour UNION ALL 
     SELECT '16' AS Hour UNION ALL SELECT '17' AS Hour UNION ALL 
     SELECT '18' AS Hour UNION ALL SELECT '19' AS Hour UNION ALL 
     SELECT '20' AS Hour UNION ALL SELECT '21' AS Hour UNION ALL 
     SELECT '22' AS Hour UNION ALL SELECT '23' AS Hour) AS Hours 
    ) AS T1, 
    UserSession AS T2 
WHERE 
    -- Logged on during, logged off during 
    (T2.SessionStart >= T1.StartHour AND T2.SessionEnd < T1.EndHour) 
    -- Logged on before, logged off during 
    OR (T2.SessionStart < T1.StartHour AND T2.SessionEnd >= StartHour AND T2.SessionEnd < T1.EndHour) 
    -- Logged on during, logged off after 
    OR (T2.SessionStart >= T1.StartHour AND T2.SessionStart < T1.EndHour AND T2.SessionEnd >= T1.EndHour) 
    -- Logged on before, logged off after 
    OR (T2.SessionStart < T1.StartHour AND T2.SessionEnd >= T1.EndHour) 
GROUP BY 
    T1.StartHour 
ORDER BY 
    T1.StartHour 

필요한 입력은 YYYY-MM-DD 형식으로 집계되는 날입니다. 카운트가 0 인 시간 동안 결과를 반환하지 않습니다.

관련 문제