0

値の 1 つが変更されたときにレコードを選択する最も効率的な方法は何ですか? 元:

アカウントが変更されたときにレコードが作成される、以下のようなアカウント履歴テーブルがあります。

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基本的にロジックは、2 行目から開始して前の行をスキャンし、アクティブの値が ( 経由で)一致しなかった場合、結果に表示します。

ライブ テスト: http://sqlfiddle.com/#!3/68136/4

于 2012-04-16T09:20:12.653 に答える
0

2通り

1) 列を追加する

update_tsmp タイムスタンプ

update または insert の後に実行されるテーブルにトリガーを置きます -- Active フィールドをチェックします -- update update_tsmp を現在のタイムスタンプに変更した場合

レコードを返すかどうかを決定するには、「最後のエントリ以降」を定義する必要があります

2) 履歴テーブルを作成する

Id AcctNb Active Created change_tsmp updates_user delete_flag

更新または削除の前に実行されるテーブルにトリガーを置きます-- レコードを履歴テーブルにコピーし、必要に応じて削除フラグをチェックします

于 2012-04-16T08:30:57.570 に答える
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 と JOIN のコンボアプローチよりもエレガントにシンプルです。

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

于 2012-04-20T13:42:28.020 に答える