registros atuais selecione SQL padrão de uma questão de log de auditoria
Pergunta
A minha memória está falhando comigo. Eu tenho uma tabela log de auditoria simples baseado em um gatilho:
ID int (identidade, PK)
Cliente int
Nome varchar (255)
Endereço varchar (255)
AuditDateTime datetime
AuditCode char (1)
Tem dados como este:
ID Cliente Nome Endereço AuditDateTime AuditCode
1 123 Bob 123 Internet Way 2009-07-17 13: 18: 06,353 I
2 123 Bob 123 Internet Way 2009-07-17 13: 19: 02,117 D
3 123 Jerry 123 Internet Way 2009-07-17 13: 36: 03,517 I
4 123 Bob 123 My Way Editado 2009-07-17 13: 36: 08,050 U
5 100 Arnold 100 SkyNet Way 2009-07-17 13: 36: 18,607 I
6 100 Nicky 100 de estrela 2009-07-17 13: 36: 25,920 U
7 110 Blondie 110 Another Way 2009-07-17 13: 36: 42,313 I
8 113 Sally 113 ainda uma outra maneira 2009-07-17 13: 36: 57,627 I
Qual seria a instrução select eficiente ser para obter todos os registros mais atuais entre a hora de início e fim FYI:?. I para inserir, D para apagar, e U para atualização
Estou faltando alguma coisa na tabela de auditoria? Meu próximo passo é criar uma tabela de auditoria que só registra mudanças, mas você pode extrair os registros mais recentes para o determinado período de tempo. Para a vida de mim eu não posso encontrá-lo em qualquer motor de busca facilmente. Ligações iria trabalhar muito. Obrigado pela ajuda.
Solução
Outro (melhor?) Para manter o histórico de auditoria é usar um 'startDate' e coluna 'endDate' em vez de um auditDateTime e coluna AuditCode. Isso é muitas vezes a abordagem no rastreamento de Tipo 2 alterações (novas versões de uma linha) em armazéns de dados.
Isso permite selecionar mais diretamente as linhas atuais (ONDE endDate é NULL), e você não vai precisar de atualizações tratam de forma diferente do que inserções ou exclusões. Você simplesmente tem três casos:
- Inserir: copiar a linha completa juntamente com uma data de início e data final NULL
- Excluir: definir a data de término da linha atual existente (endDate é NULL)
- Update: fazer um Excluir em seguida, insira
Seu selecione seria simplesmente:
select * from AuditTable where endDate is NULL
De qualquer forma, aqui está minha consulta para o seu esquema existente:
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
Referências
A cribsheet para armazéns de dados , mas tem uma seção boa em tipo 2 alterações (o que você deseja acompanhar)
página MSDN sobre data warehousing
Outras dicas
Ok, um par de coisas para as tabelas de log de auditoria.
Para a maioria das aplicações, queremos tabelas de auditoria a ser extremamente rápido na inserção.
Se o log de auditoria é verdadeiramente para diagnóstico ou por razões de auditoria muito irregulares, em seguida, os critérios de inserção mais rápida é fazer com que a mesa fisicamente ordenou em cima tempo de inserção.
E isto significa colocar o tempo de auditoria como a primeira coluna do índice agrupado, por exemplo.
create unique clustered index idx_mytable on mytable(AuditDateTime, ID)
Isto irá permitir a escolha consultas extremamente eficientes em cima AuditDateTime O (N log N) e S (1) inserções.
Se você deseja olhar para cima a sua tabela de auditoria em uma base por CustomerID, então você terá de compromisso.
Você pode adicionar um índice agrupado em cima (CustomerID, AuditDateTime), o que permitirá O (log n) de pesquisa de histórico de auditoria por cliente, no entanto, o custo será a manutenção desse índice sem cluster após a inserção - que a manutenção ser O (N log N) inversamente.
No entanto, que penalidade de tempo de inserção pode ser preferível a varredura da tabela (ou seja, O (n) Custo complexidade de tempo) que você terá que pagar se você não tiver um índice em CódigoDoCliente e esta é uma consulta regular que é realizado. Um O (n) lookup que bloqueia a tabela para o processo de escrita para uma consulta irregular pode bloquear-se escritores, por isso às vezes é do interesse dos escritores a ser um pouco mais lento se garantir que os leitores não vão estar bloqueando seus commits, porque os leitores precisam de varredura da tabela devido à falta de um índice bom para apoiá-los ....
A adição: se você está olhando para restringir a um determinado período de tempo, a coisa mais importante em primeiro lugar é o índice sobre AuditDateTime. E torná-lo agrupado como você está inserindo a fim AuditDateTime. Esta é a maior coisa que você pode fazer para tornar sua consulta eficiente desde o início.
Em seguida, se você está procurando a atualização mais recente para todos CustomerID de dentro de um determinado período de tempo, bem depois uma verificação completa dos dados, restringida por data de inserção, é necessário.
Você vai precisar fazer uma subconsulta na sua tabela de auditoria, entre o intervalo,
select CustomerID, max(AuditDateTime) MaxAuditDateTime
from AuditTrail
where AuditDateTime >= @begin and Audit DateTime <= @end
e, em seguida, incorporar em que a sua consulta de seleção adequada, por exemplo.
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
Outra abordagem é usar um sub selecione
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;
começar e terminar o tempo? por exemplo, como entre 01:00-03:00
ou iniciar e terminar data e hora? por exemplo como em 2009-07-17 13:36 a 2009-07-18 13:36