Domanda

La mia memoria mi sta venendo a mancare. Ho una semplice tabella di registro di controllo in base a un trigger:
ID int (identità, PK)
CustomerID int
Nome varchar (255)
Indirizzo varchar (255)
AuditDateTime datetime
AuditCode char (1)
Ha di dati di questo tipo:
ID CustomerID Nome Indirizzo AuditDateTime AuditCode 1 123 Bob 123 Internet via 2009-07-17 13: 18: 06,353 I 2 123 Bob 123 Internet via 2009-07-17 13: 19: 02,117 D 3 123 Jerry 123 Internet via 2009-07-17 13: 36: 03,517 I 4 123 Bob 123 My Way cura 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 Way 100 Stella 2009-07-17 13: 36: 25,920 U 7 110 Blondie 110 Un altro modo 2009-07-17 13: 36: 42,313 I 8 113 di Sally 113 Un altro modo 2009-07-17 13: 36: 57,627 I

Quale sarebbe l'istruzione select efficiente sia per ottenere tutti i record più attuali tra un tempo di inizio e di fine FYI:?. Io per l'inserimento, D per la cancellazione, e U per l'aggiornamento
Mi sto perdendo qualcosa nella tabella di controllo? Il mio prossimo passo è quello di creare una tabella di controllo che registra solo le modifiche, ma è possibile estrarre i record più recenti per il determinato lasso di tempo. Per la vita di me non riesco a trovare su qualsiasi motore di ricerca facilmente. Link avrebbe funzionato troppo. Grazie per l'aiuto.

È stato utile?

Soluzione

Un altro metodo (meglio?) Per mantenere la storia di revisione è quello di utilizzare un 'startDate' e la colonna 'endDate' piuttosto che una colonna auditDateTime e AuditCode. Questo è spesso l'approccio di tipo 2 di monitoraggio cambiamenti (nuovi versioni di una riga) nel data warehouse.

Questo consente di selezionare in modo più diretto le file attuali (DOVE endDate è NULL), e non sarà necessario per trattare gli aggiornamenti in modo diverso rispetto inserti o elimina. Devi semplicemente tre casi:

  • Inserisci: copiare la fila completa con una data di inizio e la data di fine NULL
  • Elimina: impostare la data di fine della riga corrente esistente (endDate è NULL)
  • Aggiornamento: fare un Delete quindi inserire

Il tuo selezionare sarebbe semplicemente:

select * from AuditTable where endDate is NULL

In ogni caso, ecco la mia domanda per il vostro schema esistente:

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

Riferimenti

Un cribsheet per i data warehouse , ma ha una buona sezione di tipo 2 cambi (ciò che si desidera tenere traccia)

data warehousing

Altri suggerimenti

Ok, un paio di cose per le tabelle di registro di controllo.

Per la maggior parte delle applicazioni, vogliamo tabelle di controllo di essere estremamente veloce su inserimento.

Se il registro di controllo è davvero per diagnostica o per motivi di revisione molto irregolari, quindi i criteri di inserimento più veloce è quello di rendere la tavola fisicamente ordinato sul tempo di inserimento.

E questo significa mettere il tempo di audit la prima colonna dell'indice cluster, per es.

create unique clustered index idx_mytable on mytable(AuditDateTime, ID)

Ciò consentirà di query di selezione estremamente efficienti su AuditDateTime O (log n), e O (1) inserimenti.

Se si desidera guardare la vostra tabella di controllo su una base per CustomerID, allora si avrà bisogno di scendere a compromessi.

È possibile aggiungere un indice non cluster su (CustomerID, AuditDateTime), che consentirà di O (log n) ricerca del per-cliente cronologia di controllo, ma il costo sarà il mantenimento di tale indice non cluster al momento dell'inserimento - che la manutenzione sarà O (log n) viceversa.

Comunque penalità di tempo di inserimento può essere preferibile alla scansione di tabella (vale a dire, O (n) Costo tempo complessità) che sarà necessario pagare se non si dispone di un indice su CustomerID e questa è una domanda regolare che viene eseguita. Un O (n) di ricerca che blocca il tavolo per il processo di scrittura per una query irregolare può bloccare fino scrittori, quindi a volte è nell'interesse scrittori di essere leggermente più lento se assicura che i lettori non stanno per essere bloccando i loro commit, perché i lettori hanno bisogno di scansione di tabella a causa della mancanza di un buon indice per sostenerli ....


Inoltre: se si sta cercando di limitare ad un determinato periodo di tempo, la cosa più importante prima di tutto è l'indice su AuditDateTime. E renderlo cluster come si sta inserendo in ordine AuditDateTime. Questa è la cosa più grande che si può fare per rendere la query efficiente fin dall'inizio.

Quindi, se siete alla ricerca per l'aggiornamento più recente per tutti i CustomerID di in un determinato periodo, così da allora in poi è necessaria una scansione completa dei dati, limitato dalla data di inserimento,.

Sarà necessario fare una sottoquery sulla tua tabella di controllo, tra la catena,

select CustomerID, max(AuditDateTime) MaxAuditDateTime 
from AuditTrail 
where AuditDateTime >= @begin and Audit DateTime <= @end

e poi incorporare che nella vostra query di selezione corretta, ad esempio.

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

Un altro approccio sta usando una sub selezionare

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;

di inizio e fine? per esempio come in mezzo 01:00-03:00
 o ora di inizio e data di fine? per esempio come in 2009-07-17 13:36 a 13:36 2009-07-18

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top