当其中一个值发生变化时,选择记录的最有效方法是什么? 例如:
我有一个如下所示的帐户历史记录表,其中记录在帐户更改时创建:
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)
答案 0 :(得分: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
),我们会在结果中显示它们
答案 1 :(得分:0)
2种方式
1) 添加一列
update_tsmp timestamp
在更新或插入后运行的表上放置一个触发器 - 检查活动字段 - 如果已将update update_tsmp更改为当前时间戳
现在您必须定义“自上次输入以来”以确定是否要返回记录
2) 创建历史表
Id AcctNb Active Created change_tsmp updating_user delete_flag
在更新或删除之前运行的表格上设置触发器 - 将记录复制到历史记录表,并根据需要检查删除标记 p>
答案 2 :(得分:0)
如果将来的SQL Server具有LAG窗口功能,您可以使用LAG简化前一行与当前的比较
现在在Postgresql上工作(自8.4起),它已经具有LAG和LEAD窗口功能:
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方法比ROW_NUMBER and JOIN combo方法简单明了:
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
实时测试:http://sqlfiddle.com/#!1/b1eb0/25
修改强>
LAG已在SQL Server 2012上提供:http://sqlfiddle.com/#!6/d17c0/1