기본적으로 두 가지 종류의 시간 간격이 있습니다.
presence time
과 absence time
absence time
다른 유형 (예 : 휴식, 부재, 특별한 날 등) 일 수 있으며 시간 간격이 겹치거나 교차 할 수 있습니다.
그것은 것입니다 하지 간격의 그럴듯한 조합 예를 들어, 원시 데이터에 있는지, 확실히. 존재 간격이 겹치는 것은 의미가 없지만 존재할 수 있습니다. 나는 현재 여러 가지 방법으로 존재 시간 간격을 식별하려고 노력했습니다. 가장 편안한 방법은 다음과 같습니다.
;with "timestamps"
as
(
select
"id" = row_number() over ( order by "empId", "timestamp", "opening", "type" )
, "empId"
, "timestamp"
, "type"
, "opening"
from
(
select "empId", "timestamp", "type", case when "types" = 'starttime' then 1 else -1 end as "opening" from
( select "empId", "starttime", "endtime", 1 as "type" from "worktime" ) as data
unpivot ( "timestamp" for "types" in ( "starttime", "endtime" ) ) as pvt
union all
select "empId", "timestamp", "type", case when "types" = 'starttime' then 1 else -1 end as "opening" from
( select "empId", "starttime", "endtime", 2 as "type" from "break" ) as data
unpivot ( "timestamp" for "types" in ( "starttime", "endtime" ) ) as pvt
union all
select "empId", "timestamp", "type", case when "types" = 'starttime' then 1 else -1 end as "opening" from
( select "empId", "starttime", "endtime", 3 as "type" from "absence" ) as data
unpivot ( "timestamp" for "types" in ( "starttime", "endtime" ) ) as pvt
) as data
)
select
T1."empId"
, "starttime" = T1."timestamp"
, "endtime" = T2."timestamp"
from
"timestamps" as T1
left join "timestamps" as T2
on T2."empId" = T1."empId"
and T2."id" = T1."id" + 1
left join "timestamps" as RS
on RS."empId" = T2."empId"
and RS."id" <= T1."id"
group by
T1."empId", T1."timestamp", T2."timestamp"
having
(sum( power( 2, RS."type" ) * RS."opening" ) = 2)
order by
T1."empId", T1."timestamp";
일부 데모 데이터는 SQL-Fiddle 을 참조하십시오 .
원시 데이터는 "starttime" - "endtime"
또는 형식으로 다른 테이블에 존재합니다 "starttime" - "duration"
.
아이디어는 존재 시간을 추정하기 위해 매번 열린 간격의 "비트 마스킹 된"롤링 간격을 가진 모든 타임 스탬프의 정렬 된 목록을 얻는 것입니다.
간격이 다른 스타 타임이 같더라도 바이올린이 작동하고 예상 결과를 제공합니다. 이 예제에서는 인덱스가 사용되지 않습니다.
이것이 의문의 과제를 달성하는 올바른 방법입니까, 아니면 더 우아한 방법입니까?
응답과 관련이있는 경우 : 데이터 양은 테이블 당 직원당 최대 10 만 개입니다. sql-2012를 사용하여 선행 작업의 롤링 합계를 인라인으로 계산할 수 없습니다.
편집하다:
방대한 양의 테스트 데이터 (1000, 10.000, 100.000, 1 백만)에 대해 쿼리를 실행하면 런타임이 기하 급수적으로 증가 함을 알 수 있습니다. 분명히 경고 깃발 이죠?
쿼리를 변경하고 기발한 업데이트로 롤링 합계 집계를 제거했습니다.
보조 테이블을 추가했습니다.
create table timestamps
(
"id" int
, "empId" int
, "timestamp" datetime
, "type" int
, "opening" int
, "rolSum" int
)
create nonclustered index "idx" on "timestamps" ( "rolSum" ) include ( "id", "empId", "timestamp" )
롤링 합계 계산을이 곳으로 옮겼습니다.
declare @rolSum int = 0
update "timestamps" set @rolSum = "rolSum" = @rolSum + power( 2, "type" ) * "opening" from "timestamps"
"근무 시간"테이블에서 1 백만 개의 항목에 대해 런타임이 3 초로 감소했습니다.
질문은 동일하게 유지됩니다. 이것을 해결하는 가장 효과적인 방법은 무엇입니까?
[this]
. 큰 따옴표보다 낫습니다.