2011-03-17 3 views
0

나는 정상적인 방법으로는 답을 찾을 수 없다는 어려움이 있습니다. 가능한 한 많은 쿼리를 수행하고 싶습니다. 다른 대안은이 함수를 스크립팅하고 foreach가 무수히 많은 하위 쿼리를 루프하기 때문입니다.SQL에서 항목을 페어링하고 결과를 빼는 것

MySQL 서버에 로깅 테이블이 있으므로 다음 열이 있습니다. 키, 사용자 ID, 날짜 및 위치 위치는 "시작", "로그인"및 "끝"일 수 있습니다.

각 로그인 이벤트의 "시작", "로그인"및 "종료"의 차이점을 알고 싶습니다. 누구나 사용할 수있는 SQL 쿼리에 대해 알고 있습니까? 쿼리 내에서 쿼리와 관련이 있다고 생각하지만 JOIN 만 찾을 수 있습니까?

"시작"이벤트를 선택한 다음 각 "시작"이벤트에 대해 "시작"시간 이후에 "UserID"에 대한 다음 첫 번째 로그인 이벤트를 찾아야한다고 가정합니다. 동일한 "UserID"에 대한 다음 "시작"시간) DATE_SUB()을 사용하여 차이점을 찾습니다. 두 가지 경우가 발생할 경우를 대비하여 향후 "시작"이벤트 이후에 발생하는 "로그인"또는 "종료"이벤트를 걸러내는 것이 중요합니다.

아무도 Excel에서이 작업을 수행하지 못하면 매우 감사 할 것입니다. 그 이유는 수천 개의 vlookup에서 너무 더러운 느낌을 피할 수 있기 때문입니다. PHP 또는 Perl에서이 작업을 수행하고 LIMIT 1 SQL 문을 사용하여 루프를 작성하는 것을 고려하고 있지만 괜찮은 SQL SELECT 문과 비교하면 수천 개의 SQL 쿼리를 작성할 수 있습니다.

+1

5 개의 항목이있는 예제 테이블을 표시 할 수 있습니까? 그리고이 5 개의 항목이 표시되는 것처럼 보이는 결과가 표시 될 수 있습니까? – Matt

+1

3 개의 날짜가 같은 행에 업데이트되지 않는 이유는 무엇입니까? 각 사용자가 시작 시간, 로그인 시간 및 종료 시간을 가질 것인지를 안다면 tbl (key, uid, start, login, end)과 같은 테이블을 사용하는 것이 더 나을 것입니다. – Jai

답변

0

시작일과 종료일 만 있다면 기본 접근법입니다. 나는 "로그인"위치가 어떻게 맞는지 이해하지 못하기 때문에 원하는 출력을 더 명확하게 설명하거나 쿼리를 만족스럽게 작성해야합니다. 또한 MySQL을 설치하지 않았으므로 쿼리가 SQL 서버에 있습니다 - 죄송합니다!

CREATE TABLE LogTable 
(
    id int IDENTITY, 
    userId nvarchar(20), 
    logDate datetime, 
    position nvarchar(5)  
) 
GO 

INSERT INTO LogTable (userId, logDate, position) VALUES ('User1', '2001-01-01', 'start') 
INSERT INTO LogTable (userId, logDate, position) VALUES ('User1', '2001-01-02', 'end') 
INSERT INTO LogTable (userId, logDate, position) VALUES ('User1', '2001-01-05', 'start') 
INSERT INTO LogTable (userId, logDate, position) VALUES ('User1', '2001-01-08', 'end') 
INSERT INTO LogTable (userId, logDate, position) VALUES ('User2', '2001-01-01', 'start') 
INSERT INTO LogTable (userId, logDate, position) VALUES ('User2', '2001-01-03', 'end') 
INSERT INTO LogTable (userId, logDate, position) VALUES ('User2', '2001-01-06', 'start') 
INSERT INTO LogTable (userId, logDate, position) VALUES ('User2', '2001-01-07', 'end') 
GO 

SELECT log1.userId, log1.logDate AS [start], log2.logDate AS [end], 
     DATEDIFF(d, log1.logDate, log2.logDate) AS [Diff. in Days] 
FROM LogTable log1 JOIN 
     LogTable log2 ON log1.userId = log2.userId 
WHERE log1.position = 'start' 
AND  log2.position = 'end' 
AND  log2.logDate > log1.logDate 
AND  NOT EXISTS (
    SELECT * 
    FROM LogTable logDateCheck 
    WHERE logDateCheck.userId = log1.userId 
    AND  logDateCheck.logDate >= log1.logDate 
    AND  logDateCheck.logDate <= log2.logDate 
    AND  logDateCheck.id NOT IN (log1.id, log2.id)) 
GO 

출력은 다음과 같습니다

Output from query

1

내가 MySQL은 확실하지 않다. MS SQL Server에서 다음과 같은 것을 시도해 보겠습니다.

SELECT Key, UserID, DateTime, Position, 
    (DateTime - (SELECT MAX(DateTime) FROM <table> t1 
       WHERE t1.UserID=UserID AND t1.DateTime < DateTime)) AS DiffToLastEvent 
FROM <table> 

저는 실제로이 문제를 시도하지 않았지만 그게 내가 시작했을 것입니다. 이 테이블의 모든 열을 현재 항목 앞에 사용자에게 생성 된 가장 최근 항목과 현재 항목의 시차가 포함 된 추가 필드가있는 테이블 <table>의 모든 열을 선택해야합니다.

+0

동일한 사용자가 여러 번 로그인 할 수있는 경우이 접근법은 작동하지 않습니다.이 경우에는 해당 질문이 명확하지 않습니다. –

+1

물론 그렇습니다. 이벤트와 상관없이 * 현재 이벤트와 마지막 이벤트 사이의 시간을 계산합니다. 같은 사용자에 대한 다중 로그인이 허용되면 현재 시점과 마지막 시점 사이의 시간차를 얻을 수 있습니다. 나는 "로그인"시간을 계산한다고 주장하지 않았다. –

+1

사과 - 당신 말이 맞습니다. 분명히 내 머리 속에 SQL 구문 분석기가 필요 약간 정제 ...;) –

관련 문제