2012-04-05 3 views
3

나는 타임 스탬프가있는 user_id에 대한 로그인 데이터 집합이 있습니다.SQL 서버에서 한 시간 씩 다른 레코드를 선택하는 방법

사용자는 여러 번 로그인 할 수 있지만 최소 레코드부터 최소 한 시간 씩 다른 레코드를 반환해야합니다. (사용자가 여러 명일 수 있음)

예를 들어 사용자 수준에서 중복 제거가 발생해야합니다. 24 : 14 USER1 2012-03-07

  • 30.000
  • USER1 2012-03-07 14 : 34 : 30.000
  • USER1 2012-03-07 15 : 14 : 30.000
  • USER1 2,012 -03-07 15 : 20 : 30.000
  • USER1 2012-03-07 15 : 30 : 30.000
  • USER1 2012-03-08 09 : 20 : 30.000
  • USER1 2012-03-08 9시 50분 : 30.000
  • user1 2012-03- 08 10 : 30 : 30.000
  • 사용자 2 2012-03-07 15 : 20 : 30.000

내가는 다음과 같은 기록

  • 사용자 1 2012-03-07 14시 24분을보고 싶은 것 : 30.000
  • USER1 2012-03-07 15 : 30 : 30.000
  • USER1 2012-03-08 09 : 20 : 30.000
  • USER1 2012-03-08 10 : 30 : 30.000
  • USER2 2012-03-07 15 : 20 : 30.000

================================== ======================

이 작업을 수행하는 방법은 없습니다. 깨끗한 방법? 우리는이 재귀 적으로 할 수 있지만 row_number 파티션을 사용하는 방법이있을 것으로 기대했다.

어떤 도움을 많이 주시면 감사하겠습니다!

+0

어떤 버전의 SQL Server입니까? – Glenn

답변

3

SQL Server 2005 이상에서이 CTE는 이미 선택된 LoginAts에서 시간보다 적은 시간을 제거하는 LoginAt datetimes 테이블을 반환합니다.

;with SkipHour(UserID, LoginAT, rn) as (
    select UserID, min(LoginAt), cast (1 as bigint) 
    from LogTable 
    group by UserID 
    union all 
    select SkipHour.UserID, LogTable.LoginAt, 
     row_number() over (partition by SkipHour.UserID 
          order by Logtable.LoginAt) rn 
    from SkipHour 
    inner join LogTable 
     on LogTable.UserID = SkipHour.UserID 
    where datediff(minute, SkipHour.LoginAt, LogTable.LoginAt) >= 60 
    -- Only first rows from previous generation qualify to have children 
     and rn = 1 
) 
select * 
from SkipHour 
where rn = 1 
order by UserID, LoginAT 

중요한 부분은 row_number()입니다. SQL Server는 집계 함수 나 상위 조건자를 허용하지 않으므로 rowAnter()는 loginAt datetimes를 주문하고 첫 번째 것을 유지하는 유일한 방법입니다.

Sql Fiddle playground is this way.

UPDATE :

행 번호는 개별적으로 각 세대에 적용됩니다. WITH common_table_expression (Transact-SQL) 추출물 :

분석 및 집계 기능을 CTE의 재귀 부분은 CTE에 대한 세트로 를 현재의 재귀 레벨 세트에 적용되지 않는다.ROW_NUMBER와 같은 함수는 현재 재귀 수준에 의해 전달 된 데이터의 하위 집합에서만 작동하며 전체 집합은 CTE의 재귀 부분에 적용되지 않습니다. 에 대한 자세한 내용은 J. 재귀 적 CTE에서 분석 함수 사용을 참조하십시오.

+0

안녕 니콜라! 무리 감사! 이것은 잘 작동합니다. 기본 레코드로부터의 시간이 1 시간보다 클 때 번호 매기기를 다시 시작하여 파티션을 어떻게 설명 할 수 있습니까? 예 : cte는 사용자 당 최소 항목을 가져옵니다. 그런 다음 cte 레코드보다 큰 시간 항목을 기반으로 메인 테이블에 가입합니다. row_numbers를 할당합니다. 특정 사용자 ID에 대해 row_number가 다시 시작되는 이유는 무엇입니까? CTE에서 너무 분 항목은 오전 10시 반 이며, 우리는 지금 행을 11:31 AM, (1, 2, 3은 각각 행 번호를 얻을 수) 11:35 AM, 오전 11시 40분를 얻기 위해 가입하지만, 오후 12시 10분의 ROW_NUMBER 시작을 만드는 것 1시에 돌아 오시겠습니까?) – user1316437

+0

@ user1316437 제 답변을 보시기 바랍니다. –

관련 문제