SQL Server - 需要SQL查询来识别/突出显示审计表中的特定更改

时间:2010-06-22 20:26:53

标签: sql sql-server sql-server-2005 sql-server-2008

假设我有一些数据存储在审计表中,其中主数据表上的触发器将所有发票记录更新写入此审计表。审计表包含以下数据:

InvoiceID CustomerID  ItemSold    AmountSold     SalesPerson  ModifyDate
1001      96          Widget      800            Robert       2001-1-1
1006      85          Thinger     350            Phil         2001-1-8
1001      96          Widget      800            Bobby        2001-1-9
1005      22          Widget      400            Robert       2001-1-10
1006      44          Thinger     500            Mike         2001-2-5
1001      96          Widget      250            Robert       2001-6-4

我想编写一个查询,以便在任何特定的InvoiceID时识别每当SalesPerson字段更改时(例如:每当销售人员将销售更改为他的名字时)。

所以在上面的例子中,我想确定2001-1-9发生的变化,其中InvoiceID 1001的销售从Robert转到Bobby,以及2001-6-4的变化从鲍比回到罗伯特......所以这个特定ID的两个变化。而且我还想确定2001-2-5的变化,其中InvoiceID 1006的销售从菲尔到迈克。

如何编写识别/突出显示这些更改的SQL查询?

该表当前不包含主键,但如果需要,我可以添加一个。

4 个答案:

答案 0 :(得分:3)

如果你添加一个主键(你应该这样做,从长远来看,这将使你在这个表上需要的一些查询更容易) 然后你需要的是一个自我加入。这样的事情可能会这样做:

select a.invoiceId, a.SalesPerson as FirstSalesPerson, 
    a.Modifydate as FirstModifyDate, b.SalesPerson as SecondSalesPerson, 
    B.Modifydate as SecondModifyDate  
from myaudittable a
join myadudittable b
   on a.InvoiceID = b.InvoiceID
where a.AuditIDd <>b.AuditID and a.ModifyDate < b.ModifyDate
   and a.SalesPerson<>b.SalesPerson
order by InvoiceID

答案 1 :(得分:2)

这应该这样做。

declare @Audit table (
    InvoiceID int,
    CustomerID int,
    ItemSold varchar(10),
    AmountSold int,
    SalesPerson varchar(10),
    ModifyDate datetime
)

insert into @Audit
    (InvoiceID, CustomerID, ItemSold, AmountSold, SalesPerson, ModifyDate)
    values
    (1001, 96, 'Widget', 800, 'Robert', '2001-1-1'),
    (1006, 85, 'Thinger', 350, 'Phil', '2001-1-8'),
    (1001, 96, 'Widget', 800, 'Bobby', '2001-1-9'),
    (1005, 22, 'Widget', 400, 'Robert', '2001-1-10'),
    (1006, 44, 'Thinger', 500, 'Mike', '2001-2-5'),
    (1001, 96, 'Widget', 250, 'Robert', '2001-6-4')

select a2.InvoiceID, a2.SalesPerson, a2.ModifyDate
    from @Audit a1
        inner join @Audit a2
            on a1.InvoiceID = a2.InvoiceID
                and a1.ModifyDate < a2.ModifyDate
                and a1.SalesPerson <> a2.SalesPerson

答案 2 :(得分:1)

我认为这是一个更完整的答案。它假定:

  1. 至少SQL Server 2005
  2. ModifyDate列是在审核日志中创建记录的时间。
  3. 存在身份主键AuditID

  4. declare @Audit table 
    (
        AuditID int identity(1,1),
        InvoiceID int,
        CustomerID int,
        ItemSold varchar(10),
        AmountSold int,
        SalesPerson varchar(10),
        ModifyDate datetime
    )
    
    ;with orders (InvoiceID, SalesPerson, ModifyDate, idx)
    as
    (
        select 
            InvoiceID, 
            SalesPerson, 
            ModifyDate, 
            row_number() over (partition by InvoiceID order by AuditID desc)
        from @Audit
    ) 
    
    select o2.InvoiceID, o2.SalesPerson, o2.ModifyDate from orders o1 inner join orders o2 
    on 
        o1.InvoiceID = o2.InvoiceID and 
        o1.SalesPerson <> o2.SalesPerson and
        o1.idx = o2.idx-1
    order by InvoiceID, ModifyDate desc
    

答案 3 :(得分:0)

我使用了已发布的答案中的一些零碎内容,但我能够隔离销售人员实际更改的唯一方法是使用子查询。否则我得到的结果太多了,很难找出记录改变了销售人员的实际日期。

 select InvoiceId,SalesPerson,auditdate from myaudittable where InvoiceId in 
 (select distinct a.InvoiceId 
 from myaudittable a inner join myaudittable b on a.InvoiceId = b.InvoiceId and         
 a.SalesPerson <> b.SalesPerson)                
 group by InvoiceId,SalesPerson