SQL 표준 감사 로그 질문에서 현재 레코드 선택
문제
내 기억이 실패하고 있습니다. 트리거를 기반으로 간단한 감사 로그 테이블이 있습니다.
IDint (Identity, PK)
고객 IDint
이름바르 차 (255)
주소바르 차 (255)
감사합니다날짜 시간
감사 코드숯 (1)
다음과 같은 데이터가 있습니다.
ID고객 ID이름주소감사합니다감사 코드
1 123 단발123 인터넷 웨이2009-07-17 13:18:06.353나
2 123 단발123 인터넷 웨이2009-07-17 13:19:02.117디
3 123 실내 변기123 인터넷 웨이2009-07-17 13:36:03.517나
4 123 단발123 내 편집 방법2009-07-17 13:36:08.050유
5 100 아놀드100 Skynet Way2009-07-17 13:36:18.607나
6 100 니키100 스타 웨이2009-07-17 13:36:25.920유
7 110 블론디110 다른 방법2009-07-17 13:36:42.313나
8 113 출격113 또 다른 방법2009-07-17 13:36:57.627나
시작 시간과 종료 시간 사이에 가장 많은 최신 레코드를 얻는 효율적인 선정 진술은 무엇입니까? 참고 : INSERT, D 삭제 용 D 및 업데이트 용 U입니다.
감사 테이블에 놓친 것이 있습니까? 다음 단계는 변경 사항 만 기록하는 감사 테이블을 만드는 것입니다. 그러나 주어진 시간 프레임에 대한 최신 레코드를 추출 할 수 있습니다. 내 삶을 위해 검색 엔진에서 쉽게 찾을 수 없습니다. 링크도 작동합니다. 도와 주셔서 감사합니다.
해결책
감사 기록을 유지하는 또 다른 (더 나은?) 방법은 AuditDateTime 및 AuditCode 열이 아닌 'startDate'및 'EndDate'열을 사용하는 것입니다. 이것은 종종 데이터웨어 하우스에서 유형 2 변경 (새로운 버전의 행)을 추적하는 방법입니다.
이렇게하면 현재 행을 직접 선택할 수 있으며 (EndDate가 NULL 인 경우) 업데이트를 인서트 또는 삭제와 다르게 처리 할 필요가 없습니다. 단순히 세 가지 경우가 있습니다.
- 삽입 : 시작 날짜 및 null 종료 날짜와 함께 전체 행을 복사하십시오.
- 삭제 : 기존 현재 행의 종료 날짜 설정 (EndDate is null)
- 업데이트 : 삭제 한 다음 삽입하십시오
당신의 선택은 단순히 다음과 같습니다.
select * from AuditTable where endDate is NULL
어쨌든, 여기 기존 스키마에 대한 내 쿼리가 있습니다.
declare @from datetime
declare @to datetime
select b.* from (
select
customerId
max(auditdatetime) 'auditDateTime'
from
AuditTable
where
auditcode in ('I', 'U')
and auditdatetime between @from and @to
group by customerId
having
/* rely on "current" being defined as INSERTS > DELETES */
sum(case when auditcode = 'I' then 1 else 0 end) >
sum(case when auditcode = 'D' then 1 else 0 end)
) a
cross apply(
select top 1 customerId, name, address, auditdateTime
from AuditTable
where auditdatetime = a.auditdatetime and customerId = a.customerId
) b
참조
ㅏ 데이터웨어 하우스의 침대 시트,하지만 유형 2 변경에 대한 좋은 섹션이 있습니다 (추적하고 싶은 내용)
MSDN 페이지 on 데이터웨어 하우징
다른 팁
좋아, 감사 로그 테이블에 대한 몇 가지.
대부분의 응용 프로그램의 경우 감사 테이블이 삽입시 매우 빠르게 진행되기를 원합니다.
감사 로그가 진단 또는 매우 불규칙한 감사 이유에 대한 경우 가장 빠른 삽입 기준은 삽입 시간에 물리적으로 주문하는 것입니다.
그리고 이것은 감사 시간을 클러스터 된 인덱스의 첫 번째 열 (예 :
create unique clustered index idx_mytable on mytable(AuditDateTime, ID)
이를 통해 AuditDateMe O (log n) 및 O (1) 삽입시 매우 효율적인 선택 쿼리가 가능합니다.
고객마다 감사 테이블을 찾으려면 타협해야합니다.
(CustomerID, AuditDateTime)에 비 클러스터 된 인덱스를 추가 할 수 있습니다. 이는 커스토어 당 감사 기록의 O (log n) 조회를 허용 할 수 있지만 비용은 삽입시 비 클러스터 된 색인의 유지 보수가 될 것입니다. 로그 N) 반대로.
그러나 삽입 시간 페널티는 CustomerID에 대한 색인이 없으면 지불 해야하는 테이블 스캔 (즉, O (N) 시간 복잡성 비용)보다 바람직 할 수 있으며 이는 정기적 인 쿼리입니다. 불규칙한 쿼리에 대한 작문 프로세스의 테이블을 잠그는 O (n) 조회는 작가를 차단할 수 있으므로 독자가 커밋을 차단하지 않을 것이라는 보장을 보장하면 작가의 관심사가 약간 느려집니다. 독자는 양호한 색인이 부족하여 스캔을 테이블 스캔해야하기 때문에 ....
추가 : 주어진 기간으로 제한하려는 경우 가장 중요한 것은 무엇보다도 AuditDateTime의 색인입니다. AuditDateTime 순서로 삽입 할 때 클러스터링하십시오. 이것은 처음부터 쿼리를 효율적으로 만들기 위해 할 수있는 가장 큰 일입니다.
다음으로, 주어진 시간대 내에 모든 CustomerID에 대한 최신 업데이트를 찾고 있다면 삽입 날짜로 제한된 데이터를 완전히 스캔해야합니다.
감사 테이블의 범위간에 하위 쿼리를 수행해야합니다.
select CustomerID, max(AuditDateTime) MaxAuditDateTime
from AuditTrail
where AuditDateTime >= @begin and Audit DateTime <= @end
그런 다음이를 선택한 쿼리에 통합하십시오 (예 :).
select AuditTrail.* from AuditTrail
inner join
(select CustomerID, max(AuditDateTime) MaxAuditDateTime
from AuditTrail
where AuditDateTime >= @begin and Audit DateTime <= @end
) filtration
on filtration.CustomerID = AuditTrail.CustomerID and
filtration.AuditDateTime = AuditTrail.AuditDateTime
다른 접근법은 하위 선택을 사용하는 것입니다
select a.ID
, a.CustomerID
, a.Name
, a.Address
, a.AuditDateTime
, a.AuditCode
from myauditlogtable a,
(select s.id as maxid,max(s.AuditDateTime)
from myauditlogtable as s
group by maxid)
as subq
where subq.maxid=a.id;
시작 및 종료 시간? 예를 들어 오전 1시에서 오전 3시 사이
또는 시작 및 종료 날짜 시간? 예 : 2009-07-17 13:36 ~ 2009-07-18 13:36