2012-01-13 6 views
2

私はこの場合DB2を使用していますが、これには一般的なSQLの答えがあります。私は可能な限りデータを簡素化しました。私は「クレーム」と呼ばれるものについての行動を数えています。それぞれのクレームは固有のクレーム番号を持っています。各アクションは、 "hhmm"という形式でタイムスタンプされます。実際には、私は行動をカウントしていない、私はアクションセッションを数えている - ほとんどの時間、人は1つの主張に対して1つのアクションを実行し、それは1つのアクションセッションです。しかし、ある人が1つのクレームに対して複数のアクションを数秒または数分で実行する場合もあります。これも1つのアクションセッションになります。しかし、誰かが午前10時にクレームに対して何らかのアクションを実行した後、午後1時にその同じクレームに対してアクションを実行した場合、それらは2アクションセッションになります。私の目的のために、何かアクションセッションを2つのアクションセッションにするための時間枠は3時間ですが、もちろんそれは任意です。そして、真夜中を越える窓の心配はありません。また、私はこのデータへの読み取り専用アクセスを持っており、これを1つのステートメントで行う必要があります。ありがとう。結合の "等価"と同じ "近い"にする

だから、ここではいくつかのデータです(表:ACTIONS):

CLAIM_NO ACTTIME 
AA  1424 
BB  1134 
CC  1221 
DD  1425 
DD  1512 
EE  1619 
FF  0928 
FF  1518 
GG  1348 
HH  1332 
II  1350 

私は(第2 DDレコードがなくなっていることに注意してくださいが、2番目のFFレコード

CLAIM_NO ACTTIME 
AA  1424 
BB  1134 
CC  1221 
DD  1425 
EE  1619 
FF  0928 
FF  1518 
GG  1348 
HH  1332 
II  1350 

にその電源を入れたいですそこにまだある)。

私は、CLAIM_NOが等しいこととACTTIMEが3時間前と1分前の間であることを条件として、自分自身にテーブルを参加させることでこれを達成しました。これは、私が属していない行を取得することができますし、それらを排除するためにEXCEPTを使います。

with excepto as (
select a.claim_no, b.acttime 
from actions a 
join actions b 
on a.claim_no=b.claim_no 
    and a.acttime between (b.acttime-300) and (b.acttime-1) 
) 
select * from actions except select * from excepto 

しかし、私はこれを1回の結合で行いたいので、「不要」は必要ありません。これはパフォーマンスが向上することを期待しています。私の実際のデータには、もちろん、より多くの行が使用する列が増えています。そして、その文を除外すると、クエリが全体的に遅くなっているようです。私は "with"ステートメントを使って一貫性のあるテンポラリテーブルをたくさん使用していますが、それらのパーツの合計よりもはるかに遅いようです。 acttimeを想定し

+0

どのバージョンのDB2ですか?機能によっては、一部のバージョンでは使用できないものがあります。また、あなたは 'int'と思われるものとして時間を保存していますか?あなたは長期的に良いことよりも自分自身を悪くするかもしれません。それを 'time'カラムに変更してください(そして、適切な場合は' timestamp'に日付と組み合わせてください)。 –

+0

私のDB2のバージョンは、iSeries用のV6R1ですと、私は信じています。 LAGとOVERは私には利用できません。私はこのスキーマを作っていないので、他の誰かが行ったので、intとして時刻を格納しています。 – Chud

+0

私は答えを加えました。 3時間に1回以上の追加がある場合はどうなりますか?最初の結果を表示するだけです。また、 'OVER()'は 'ROW_NUMBER()' OLAP関数の一部として利用できますが、そこに 'ORDER BY 'として指定したもの以上のインデックスが必要です。 –

答えて

0

私はこの忘れのために少し愚かな感じ...

あなたはexceptを必要としない - ないことexceptionと呼ばれる利用可能参加がありますまさにあなたが(と私は頻繁にそれを使用しました)欲しい:

SELECT a.claim_no, a.acttime 
FROM actions as a 
EXCEPTION JOIN actions as b 
ON b.claim_no = a.claim_no 
AND b.acttime >= a.acttime - 300 
AND b.acttime < a.acttime 

はあなたの結果セットを獲得

claim_No  acttime 
============================ 
AA   1,424 
BB   1,134 
CC   1,221 
DD   1,425 
EE   1,619 
FF    928 
FF   1,518 
GG   1,348 
HH   1,332 
II   1,350 

(残念ながら、少なくとも3時間に1回は誰かに変更を加えてもらうことはできません。最初のものが表示されます。私は適切なエントリを検出するために、あなたが6ウェイ自己結合のようなものを必要としていると思います。

+0

パフォーマンスが向上しました。どうもありがとう。完璧な結果を得ることに対する懸念について、私は幸いにも完璧な結果は必要ありません(少なくとも、アクションを実行する人々がシステムのゲーム方法を理解するまで)。今のところ、これは私が以前必要だった結果であり、受け入れ可能なパフォーマンス(前にはなかった)です。そして私は少し学んだ。 – Chud

3

が整数列である:

select * 
from (
    select claim_no, 
      acttime, 
      acttime - lag(acttime, 1, acttime) over (partition by claim_no order by acttime) as diff 
    from actions 
) t 
where diff = 0 or diff > 300 
order by claim_no 
+0

私はOPではありませんが、これはDB2(V6R1 iSeries)の私のバージョンでは実行されません...おそらく実行しているものをリストすることができますか? –

+0

@ X-Zero:私は9.7 LUWで試しました。私はテストに利用できるものは何もありませんが、マニュアルによれば、9.5でも動作するはずです(Oracle、PostgreSQL、Teradataでも動作します) –

+0

アイデアはありがたいですが、私はV6R1をiSeries上に置いています。動作しません。私はそれが古いコマンドのセットと論理を複製できるかどうかを確かめようとしています。 – Chud

関連する問題