Frage

Mein Gedächtnis versagt mir. Ich habe eine einfache Audit-Log-Tabelle auf einem Auslöser basiert:
ID int (Identität, PK)
CustomerID int
Name varchar (255)
Adresse varchar (255)
AuditDateTime Datetime
AuditCode char (1)
Es hat Daten wie folgt:
ID CustomerID Name Adresse 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 Edited 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 Star Way 2009-07-17 13: 36: 25.920 U 7 110 Blondie 110 Ein anderer Weg 2009-07-17 13: 36: 42,313 I 8 113 Sally 113 noch eine weitere Möglichkeit 2009-07-17 13: 36: 57,627 I

Was die effiziente select-Anweisung sein würde, alle aktuellen Datensätze zwischen einer Start- und Endzeit erhalten FYI:?. I für Einfügen D für Löschen, und U für Update
Fehle ich etwas in der Audit-Tabelle? Mein nächster Schritt ist es, eine Audit-Tabelle zu erstellen, die nur die Änderungen aufzeichnet, aber Sie können die neuesten Datensätze für den gegebenen Zeitrahmen extrahieren. Für das Leben von mir kann ich es nicht auf jeder Suchmaschine leicht finden. Links wäre zu arbeiten. Danke für die Hilfe.

War es hilfreich?

Lösung

Eine andere (bessere?) Methode Audit-Historie zu halten, ist eine ‚startdate‘ zu verwenden und ‚endDate‘ Spalte anstatt eine auditDateTime und AuditCode Spalte. Dies ist häufig der Ansatz bei der Verfolgung Typ-2-Änderungen (neue Versionen einer Reihe) in Data Warehouse.

Auf diese Weise können Sie mehr direkt die aktuellen Zeilen auswählen (WHERE endDate NULL ist), und Sie werden nicht Updates behandeln müssen anders als Einlagen oder löscht. Sie müssen lediglich drei Fälle:

  • Einfügen: Kopieren Sie die vollständige Reihe zusammen mit einem Startdatum und Enddatum NULL
  • Löschen: Geben Sie das Enddatum der bestehenden aktuellen Zeile (endDate ist NULL)
  • Update: tun, um ein Löschen dann auf Einfügen

Sie wählen würde einfach sein:

select * from AuditTable where endDate is NULL

Wie auch immer, hier ist meine Abfrage für Ihr vorhandenes Schema:

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

Referenzen

cribsheet für Data Warehouse , hat aber einen guten Teil auf Typ-2-Änderungen (was Sie verfolgen möchten)

MSDN-Seite auf Data Warehousing

Andere Tipps

Ok, ein paar Dinge, für Audit-Log-Tabellen.

Für die meisten Anwendungen wollen wir Audit-Tabellen für das Einfügen von extrem schnell sein.

Wenn das Prüfprotokoll wirklich für diagnostische oder für sehr unregelmäßig Prüfung Gründe, so ist die schnellsten Einführungskriterien sind die Tabelle nach dem Einsetzen Zeit physisch bestellt zu machen.

Und das bedeutet, die Prüfungszeit als die erste Spalte des gruppierten Index zu setzen, z.

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

Dies wird für die äußerst effiziente Auswahlabfragen auf AuditDateTime O (log n) und O (1) Einfügungen ermöglichen.

Wenn Sie Ihre Audit-Tabelle sehen auf einer Pro CustomerID Basis, dann müssen Sie Kompromisse eingehen.

Sie können einen nicht gruppierten Index auf (CustomerID, AuditDateTime) hinzufügen, die für O ermöglichen (log n) Nachschlag von pro-Kundenaudit Geschichte, aber die Kosten werden die Aufrechterhaltung dieses nicht gruppierten Index beim Einfügen sein -, dass die Wartung wird sein O (log n) umgekehrt.

Allerdings kann das Einsetzen Zeitstrafe auf den Tisch Scan vorzuziehen sein (das heißt, O (n) Zeit Komplexität Kosten), die Sie zahlen müssen, wenn Sie auf CustomerID keinen Index haben, und dies ist eine regelmäßige Abfrage, ist durchgeführt. Ein O (n) Lookup, die die Tabelle für den Schreibvorgang für eine unregelmäßige Abfrage sperren Schriftsteller blockieren kann, so ist es manchmal in Schriftsteller Interessen etwas langsamer sein, wenn es garantiert, dass die Leser gehen zu blockieren ihre Commits nicht, weil die Leser wegen eines Mangels eines guten Index um sie zu Tabellen-Scan müssen ....

unterstützen

Zusatz: Wenn Sie auf einen bestimmten Zeitraum zu beschränken suchen, ist das Wichtigste, was in erster Linie ist der Index auf AuditDateTime. Und machen es gruppierten, wie Sie in AuditDateTime Reihenfolge einfügen. Dies ist die größte Sache, die Sie tun, um Ihre Abfrage effizient von Anfang an.

machen

Als nächstes, wenn Sie für das letzte Update für alle CustomerID die innerhalb einer bestimmten Zeit suchen, und danach wird ein Scan der Daten durch Einfügen Datum beschränkt, ist nicht erforderlich.

Sie müssen eine Unterabfrage auf Ihrer Audit-Tabelle tun, zwischen dem Bereich,

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

und dann übernehmen, in der Auswahlabfrage richtig, zB.

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

Ein weiterer Ansatz wird mit einem Unter wählen

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;

Start- und Endzeit? beispielsweise zwischen 1.00 bis 3.00
 oder Start- und Enddatum der Zeit? beispielsweise in 2009-07-17 13.36 bis 13.36 2009-07-18

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top