2010-01-25 5 views
1

사용자가 작업을 수행 할 때마다 하나의 행을 포함하는 Occurrences 테이블이 있습니다. 사용자가 하루에 여러 번 행동을 취합니다. 그것은 다음과 같습니다SQL - 주어진 트랜잭션의 인스턴스 수를 계산 및 요약 (범위 내)

범위에서 매일
Date  Username 
------ -------- 
1/1/9  User1 
1/1/9  User1 
1/1/9  User2 
1/2/9  User1 
1/2/9  User3 
1/3/9  User1 
1/3/9  User1 
1/3/9  User1 
1/3/9  User2 
1/3/9  User3 
1/4/9  User1 
1/5/9  User1 
1/6/9  User1 
1/7/9  User1 

, 내가 작업을 여러 번 촬영 ​​한 사람들의 수를 표시하고 싶습니다 - 6과 10 사이, 2, 5 번 사이의 말을하자 시간, 그리고 10 배 이상. 그러나 다른 요일에 해당 작업을 반복하여 해당 작업의 다른 인스턴스로 계산하는 것이 좋습니다. 예를 들어, 사용자가 첫 번째 날에 3 번 작업을하고 다음 날에 다시 # 번 작업을 한 경우 사용자가 작업을 2 번 수행 했으므로 2 ~ 5 번에 있어야합니다 기둥.

위의 샘플 데이터에 해당하는 결과 집합은 다음과 같습니다 결과의 각 행은 특정 일에만에 대한 반복 작업 의 # 수를 계산

 #_of_people  #_of_people  #_of_people  
     who_did_action who_did_action who_did_action   
Date 2to5_times  6to10_times  more_than_10  Total 
----- -------------- -------------- -------------- ----- 
1/1/9 0     0     0     0 
1/2/9 1     0     0     1 
1/3/9 3     0     0     3 
...  
1/7/9 0     1     0     1   

주 - 누적되지 않습니다.

  • 1/1/9 행은 첫날이므로 모든 동작이 첫 번째로 간주됩니다.
  • 1/2/9 행은 User1 만 반복했기 때문에 1, 0, 0, 1입니다. 사용자 3이 처음입니다.
  • User1이 두 번 반복되고 User2가 한 번 반복되며 User3이 한 번 반복되기 때문에 1/3/9 행은 3, 0, 0, 3입니다.
  • User1이 6 번 반복되었으므로 1/7/9 행은 0, 1, 0, 1입니다.
+0

날짜는 datetime 데이터 형식입니다. 그러나 나는 필요하다면 무엇이든간에 모든 것을 전환하게되어 기쁘다. :) – Robert

+0

어떤 버전의 SQL Server입니까? 이 경우에는 –

+0

2008이지만 실제로는. 가능한 경우 비 버전 특정 기능을 사용하는 것을 선호하지만 그렇지 않은 경우 걱정하지 않아도됩니다. – Robert

답변

1

베스트 나는 검증되지 않은, 함께 올 수 있습니다 : 당신이 날짜 간격을 재설정 할 수있는 번호를 얻을 수있는 경우

DECLARE @username VARCHAR(40) 
DECLARE @date DATETIME 
DECLARE @counter INT 
    SET @counter = 1 

WITH occur AS (
    SELECT DISTINCT 
      CONVERT(VARCHAR(10), o.date, 101) AS dt, 
      o.username 
     FROM OCCURRENCES o 
    ORDER BY o.username, dt), 
    occur_rank AS (
    SELECT x.dt, 
      @username = x.username, 
      @date = CAST(x.dt AS DATETIME), 
      CASE WHEN @username = x.username AND @date + 1 = x.date THEN @counter = @counter + 1 ELSE @counter = 1 END AS rank 
     FROM occur x 
    ORDER BY x.username, x.dt) 
    SELECT or.dt, 
     SUM(CASE WHEN or.rank BETWEEN 2 AND 5 THEN 1 ELSE 0 END) AS 2_to_5, 
     SUM(CASE WHEN or.rank BETWEEN 6 AND 10 THEN 1 ELSE 0 END) AS 6_to_10 
    FROM occur_rank or 
GROUP BY or.dt 

가, 나머지는 간단합니다. 하지만 none of the SQL Server ranking functions support that. 따라서 변수가 수동으로 증가합니다.

첫 번째 CTE 인 occur은 날짜와 연결된 사용자 이름 목록을 반환합니다. 두 번째 CTE는 최종 출력물의 순위를 추가하여 그 위에 구축됩니다.

+0

변환은 DATETIME 데이터 유형이기 때문에'DATE' 열의 시간 부분을 제거하는 데 필요합니다. –

+0

당신은 내 마음을 읽습니다. :) 나는 지금 이것을 시도하고있다. COUNT (*)와 'num_occur'사이에 쉼표가 "as dt"와 "as"뒤에 있어야합니다. 맞습니까? – Robert

+0

@ 로버트 : 누락 된 쉼표가 수정되었습니다. AS는 테이블 별칭을 정의하는 데 필요하지 않지만 일관성을 유지해야합니다. –

0

상관 하위 쿼리가있는 파생 테이블을 사용했습니다.

상관 하위 쿼리는 해당 행의 사용자 이름에 해당하는 행 날짜를 포함하여 고유 날짜의 수를 계산하는 열 ActionCount를 생성합니다.

결과 파생 테이블은 각 날짜, 사용자 이름 및 ActionCount를 나열합니다.

외부 쿼리는 결과를 Date로 그룹화하고 ActionCounts의 개수를 2와 5, 6과 10, 10보다 큰 것으로 계산하고 총합에 대해 1보다 큰 ActionCount를 1로 설정합니다 '반복').

select 
    [Date], 
    sum(case when [ActionCount] between 2 and 5 then 1 else 0 end) [#_of_people_who_did_action_2to5_times], 
    sum(case when [ActionCount] between 6 and 10 then 1 else 0 end) [#_of_people_who_did_action_6to10_times], 
    sum(case when [ActionCount] > 10 then 1 else 0 end) [#_of_people_who_did_action_more_than_10], 
    sum(case when [ActionCount] > 1 then 1 else 0 end) [Total] 
from (
    select distinct 
     dt.[Date], 
     dt.[Username], 
     (select count(distinct [Date]) from OCCURRENCES cd where cd.[Username] = dt.[Username] and cd.[Date] <= dt.[Date]) [ActionCount] 
    from OCCURRENCES dt 
) a 
group by [Date] 
관련 문제