SQL11gでこれを行うにはいくつかの方法があります。動作中のMODEL句は次のとおりです。
SQL> with data as (select t1.t1_id, nvl(t2.bin_str, '0000') bin_str
2 from table1 t1
3 left outer join table2 t2
4 on t1.t1_id = t2.t1_id)
5 select t1_id, new_bin_str bin_str
6 from (select *
7 from data
8 model
9 partition by (t1_id)
10 dimension by (row_number() over (partition by t1_id order by bin_str) rn )
11 measures (bin_str, cast(null as varchar2(16)) new_bin_str,
12 count(*) over (partition by t1_id ) c)
13 rules (
14 new_bin_str[any] order by rn =
15 case when bin_str[cv() - 1 ] is null
16 then bin_str[cv()]
17 else cast(utl_raw.bit_or(new_bin_str[cv()-1],bin_str[cv()]) as varchar2(16))
18 end ))
19 where c = rn;
T1_ID BIN_STR
---------- --------------------
1 0000
2 0101
3 1100
これを分解しましょう。
SQL> with data as (select t1.t1_id, nvl(t2.bin_str, '0000') bin_str
2 from table1 t1
3 left outer join table2 t2
4 on t1.t1_id = t2.t1_id)
これは、関心のあるすべてのデータを含む基本クエリです。
ここで、これをXOR(utl_raw.bit_orから入手可能)し、T1_IDごとの最終結果のみを表示する必要があります。
model句は私たちのためにこれを行うことができます。まず、計算を特定のT1_IDに分離するために、「パーティション」を定義します。
9 partition by (t1_id)
次に、各行に順序を適用して、毎回同じように処理します。つまり、T1_ID = 3の場合、0101と1100があるので0101 XOR 1100
、その結果を計算して計算します。0101 XOR 1100 = res
3番目のバイナリ「0001」があった場合は、それを実行したいと思いres XOR 0001
ます。最終的には最終結果のみに関心があるため、行番号を使用してこれをフィルタリングできます。
10 dimension by (row_number() over (partition by t1_id order by bin_str) rn )
また、1行あたりの行数T1_ID
も維持します。
12 count(*) over (partition by t1_id ) c)
つまり、rn = c
これが各のデータセットの最終結果である場合T1_ID
。
対策条項
11 measures (bin_str, cast(null as varchar2(16)) new_bin_str,
これで、私たちが取り組んでいるものになります。つまりbin_str
、しかしまた、私が空白の列を定義したことがわかりますnew_bin_str
。これは、XOR演算の結果を保持する保持列になります。
これで、計算部分はXORを実行する部分になります。
14 new_bin_str [any] rn =15による順序bin_str[cv()-1]がnullの場合16 then bin_str [cv()] 17 else cast(utl_raw.bit_or(new_bin_str [cv()-1]、bin_str [cv ()])as varchar2(16))18 end))
つまり、最初の行のすべての行(new_bin_str [ANY])には、の値を使用しますbin_str
が、後続のすべての行には、前の行new_bin_str
とXORを現在のbin_str
値に使用します。これにより、次の出力が得られます。
T1_ID RN BIN_STR NEW_BIN_STR C
---------- ---------- -------------------- ---------------- ----------
1 1 0000 0000 1
2 1 0101 0101 1
3 1 0100 0100 2
3 2 1000 1100 2
これで、NEW_BIN_STRに必要な結果が得られましたが、すべての断続的な「ワークアウト」も含まれていることがわかります。したがって、c = rnでフィルタリングして、次のようにします。
T1_ID RN BIN_STR NEW_BIN_STR C
---------- ---------- -------------------- ---------------- ----------
1 1 0000 0000 1
2 1 0101 0101 1
3 2 1000 1100 2
外側の選択で、T1_ID
とを選択するだけNEW_BIN_STR
です。
他の方法は、再帰的因子サブクエリ、ユーザー定義の集計(たとえば、listaggのようにXORを実行したもの)、またはおそらくxquery(1つは考えていませんが、それを実行する能力があるかもしれません)です。