0

当其中一个值发生更改时,选择记录的最有效方法是什么?前任:

我有一个如下所示的帐户历史记录表,其中在帐户更改时创建记录:

Id  AcctNb Active Created
8   123456 1      01/03/2012
6   123456 0      01/01/2012

我喜欢找到一种有效的方法来返回自上次条目以来活动状态发生变化的记录。

更新

我目前使用的查询有效但效率低下”

select d1.acctNb,d1.active, d2.active 
from d044 d1 , d044 d2 
where d1.created = '2012-04-14'
and d1.acctNb = d2.acctNb 
and d2.created = (select max(d.created) from d044 d where d.acctNb = d2.acctNb and d.id != d1.id)   
and (d1.active != d2.active)
4

3 回答 3

1

尝试这个:

create table log
(
  log_id int identity(1,1) primary key,
  acct_id int not null,
  active bit not null,
  created datetime not null
);


insert into log(acct_id, active,created)
values
(1,1,'January 1, 2012'),
(1,1,'January 2, 2012'),
(1,0,'January 3, 2012'),
(1,0,'January 4, 2012'),
(1,1,'January 5, 2012'),
(2,0,'February 1, 2012'),
(2,1,'February 2, 2012'),
(2,0,'February 3, 2012'),
(2,1,'February 4, 2012'),
(2,1,'February 5, 2012');

解决方案:

with serialize as
(
  select row_number() 
  over(partition by acct_id order by created) rx,
  *
  from log
)
select ds.acct_id, 
ds.active ds_active, 
pr.active pr_active,

ds.created

from serialize ds -- detect second row
join serialize pr -- previous row
on pr.acct_id = ds.acct_id
and ds.rx = pr.rx + 1

where ds.rx >= 2 and
pr.active <> ds.active

查询输出:1月3日、1月5日、2月2日、2月3日、2月4日

这些是活动发生变化的日期(检测到)

基本上逻辑是,从第二行开始,我们扫描它的前一行,如果它们的活动值不匹配(通过WHERE pr.active <> ds.active),我们将它们显示在结果中

现场测试:http ://sqlfiddle.com/#!3/68136/4

于 2012-04-16T09:20:12.653 回答
0

If future SQL Server will have LAG windowing function, you can simplify the comparison of previous row to current by using LAG

This works now on Postgresql(since 8.4), it already has LAG and LEAD windowing function:

create table log
(
  log_id serial primary key,
  acct_id int not null,
  active boolean not null,
  created timestamp not null
);


insert into log(acct_id, active,created)
values
(1,true,'January 1, 2012'),
(1,true,'January 2, 2012'),
(1,false,'January 3, 2012'),
(1,false,'January 4, 2012'),
(1,true,'January 5, 2012'),
(2,false,'February 1, 2012'),
(2,true,'February 2, 2012'),
(2,false,'February 3, 2012'),
(2,true,'February 4, 2012'),
(2,true,'February 5, 2012');

LAG approach is elegantly simpler than ROW_NUMBER and JOIN combo approach:

with merge_prev as
(
    select     
        acct_id, created, 

        lag(active) over(partition by acct_id order by created) pr_active, -- previous row's active
        active sr_active -- second row's active

    from log
) 

select * 
from merge_prev
where 
    pr_active <> sr_active 

Live test: http://sqlfiddle.com/#!1/b1eb0/25

EDIT

LAG is already available on SQL Server 2012: http://sqlfiddle.com/#!6/d17c0/1

于 2012-04-20T13:42:28.020 回答
0

2种方式

1)添加一列

update_tsmp 时间戳

在更新或插入之后运行的表上放置一个触发器——检查活动字段——如果它已将更新 update_tsmp 更改为当前时间戳

现在您必须定义“自上次条目以来”以确定是否要返回记录

2)创建历史表

Id AcctNb Active Created change_tsmp updates_user delete_flag

在更新或删除之前运行的表上放置触发器——将记录复制到历史表中,并酌情检查删除标志

于 2012-04-16T08:30:57.570 回答