Sql 为什么值发生更改我们可以查询此表以查看什么/什么时候发生了更改。在这种情况下,您可以直接使用distinct对除RunKey和Rundate之外的所有列进行查询,然后将该表与该行数据的min(Rundate)和min(RunKey)进行自联接。这类似于“只
Sql 为什么值发生更改我们可以查询此表以查看什么/什么时候发生了更改。在这种情况下,您可以直接使用distinct对除RunKey和Rundate之外的所有列进行查询,然后将该表与该行数据的min(Rundate)和min(RunKey)进行自联接。这类似于“只,sql,sql-server,tsql,Sql,Sql Server,Tsql,为什么值发生更改我们可以查询此表以查看什么/什么时候发生了更改。在这种情况下,您可以直接使用distinct对除RunKey和Rundate之外的所有列进行查询,然后将该表与该行数据的min(Rundate)和min(RunKey)进行自联接。这类似于“只插入更改”,这是一个更好的想法。也就是说,不是用未更改的行归档该表,而是在有更改时才插入。这将减小表的大小,并消除您正在创建的额外表。这是否符合业务需求?是否有一种方法也可以捕获旧的价值?这是这里的关键,他想知道更改日期、旧值和新值,以及更改的
为什么值发生更改我们可以查询此表以查看什么/什么时候发生了更改。在这种情况下,您可以直接使用distinct对除RunKey和Rundate之外的所有列进行查询,然后将该表与该行数据的min(Rundate)和min(RunKey)进行自联接。这类似于“只插入更改”,这是一个更好的想法。也就是说,不是用未更改的行归档该表,而是在有更改时才插入。这将减小表的大小,并消除您正在创建的额外表。这是否符合业务需求?是否有一种方法也可以捕获旧的价值?这是这里的关键,他想知道更改日期、旧值和新值,以及更改的列。因此,与插入包含更改的整行不同,他们只想查看更改的特定列、更改日期以及新旧值。更改日期是runDate,假设您每天都运行它。因此,只有更改了才会得到新行,并且日期将是getdate(),它将显示更改的日期。从另一个角度来看,这真的是走了太多的4步。这种方法向您显示更改以及更改的时间,仅在更改时显示。它解决了核心问题,而不必为糟糕的设计使用解决方案IMHO@bm11是的,触发器既可以访问旧值,也可以访问新值。我用实际样本数据对此进行了测试,效果非常好。我正在用大约900k行的完整数据集进行测试。它运行得非常慢,因为我有26列要跟踪更改,而且似乎cte0会为每个运行键的每一列生成一行。@bm11请参阅编辑第二个选项。我将脚本添加到一个光标上,该光标在帐号上迭代并插入到我的表中。适用于所有以前的记录,并将继续创建触发器。您知道如何使用触发器提取列名吗?当我运行nightly insert时,我希望它在帐号级别查看最新的RunKey并进行比较,以查看是否发生了任何更改。 |AccountNo | RunKey | RunDate | Address | Salary | PromotionDate| ---------------------------------------------------------------------------- | 12345 | 2 | 06/20/2017 | 123 Main Street | 60,000 | 01/15/2017 | | 12345 | 3 | 06/21/2017 | 123 Main Street | 60,000 | 01/15/2017 | | 12345 | 4 | 06/22/2017 | 123 Main Street | 65,000 | 06/21/2017 | |AccountNo | RunKey | RunDate | Address | AddressLAG |AddressFlag| Salary | SalaryLAG |SalaryFlag| PromotionDate|PromotionDateLag|PromotionFlag| ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | 12345 | 2 | 06/20/2017 | 123 Main Street | 123 Main Street | 0 | 60,000 | 60,000 | 0 | 01/15/2017 | 01/15/2017 | 0 | | 12345 | 3 | 06/21/2017 | 123 Main Street | 123 Main Street | 0 | 60,000 | 60,000 | 0 | 01/15/2017 | 01/15/2017 | 0 | | 12345 | 4 | 06/22/2017 | 123 Main Street | 123 Main Street | 0 | 65,000 | 60,000 | 1 | 01/15/2017 | 06/21/2017 | 1 | | RunKey | AccountNo | ChangedCol | PrevRunDate | RunDate | PrevValue | NewValue | ------------------------------------------------------------------------------------------- | 4 | 12345 | Salary | 06/21/2017 | 06/22/2017 | 60,000 | 65,000 | | 4 | 12345 | PromotionDate | 06/21/2017 | 06/22/2017 | 01/15/2017 | 06/21/2017 |
declare @source table (
AccountNo int
,Address varchar(256)
,Salary decimal(16,4)
,PromotionDate datetime)
insert into @source
values
(12345,'123 Main Street',60000,'20170115')
declare @audit table (
AccountNo int
,Address varchar(256)
,Salary decimal(16,4)
,PromotionDate datetime
,RunDate datetime)
--load the audit table with the current version of the source table
insert into @audit
select *, getdate() from @source
--show that the tables match currently
select * from @source
select * from @audit
--insert into @audit if there are any changes (notice we haven't made any updates yet)
insert into @audit
select AccountNo, Address, Salary, PromotionDate, getdate() from @source
except
select AccountNo, Address, Salary, PromotionDate, getdate() from @audit
--show that a record WAS NOT inserted since there was no change. There is only 1 record, the orignal version
select * from @audit
--update the promotion and salary
update @source
set
PromotionDate = '20170331'
,Salary = '65000'
--insert into @audit if there are any changes
insert into @audit
select AccountNo, Address, Salary, PromotionDate, getdate() from @source
except
select AccountNo, Address, Salary, PromotionDate, getdate() from @audit
--show that a record was inserted since there was a change
select * from @audit
Declare @YourTable Table ([AccountNo] int,[RunKey] int,[RunDate] date,[Address] varchar(50),[Salary] int,[PromotionDate] date)
Insert Into @YourTable Values
(12345,2,'06/20/2017','123 Main Street',60000,'01/15/2017')
,(12345,3,'06/21/2017','123 Main Street',60000,'01/15/2017')
,(12345,4,'06/22/2017','123 Main Street',65000,'06/21/2017')
;with cte as (
Select A.AccountNo
,A.RunKey
,A.RunDate
,B.*
,PreValue=Lag(Value) over (Partition By AccountNo,Item Order by RunDate)
,PreDate =Lag(RunDate) over (Partition By AccountNo,Item Order by RunDate)
From @YourTable A
Cross Apply ( values ('Address' ,cast(A.[Address] as varchar(max)))
,('Salary' ,cast(A.[Salary] as varchar(max)))
,('PromotionDate',cast(A.[PromotionDate] as varchar(max)))
) B (Item,Value)
)
Select *
From cte
Where Value<>PreValue and PreValue is not null