2

Oracle 11G

  • Table1にはT1_IDがあります
  • Table2には、T1_IDと2進数を表す文字列(BIN_STR)があります

    1. Table1.T1_IDがTable2にない場合、戻り値は0の文字列です
    2. Table1.T1_IDがTable2で1回だけ見つかった場合、戻り値はTable2の文字列です。
    3. Table1.T1_IDがTable2で複数回見つかった場合、戻り値はTable2の文字列のビットごとのORである必要があります。

例:

表1

T1_ID 
    1 
    2 
    3

表2にはこれらのレコードがあります

T1_ID   BIN_STR 
    2    '0101'
    3    '0100'
    3    '1000'

結果セットには

T1_ID   BIN_STR 
    1    '0000'
    2    '0101'
    3    '1100'

私は持っています:

SELECT Tbl1.T1_ID,
       CASE (SELECT COUNT(*) FROM Table2 Tbl2 WHERE Tbl1.T1_ID = Tbl2.T1_ID)
         WHEN 0 THEN '0000'
         WHEN 1 THEN (SELECT Tbl2.BIN_STR FROM Table2 Tbl2 WHERE Tbl1.T1_ID = Tbl2.T1_ID)
         ELSE ???
       END AS "BINSTR"
FROM Table1 Tbl1

これは、ストアドプロシージャからのカスタム関数呼び出しで実行できることを私は知っています。SQL PLUSでそれを行う方法はありますか?

4

2 に答える 2

0

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 = res3番目のバイナリ「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つは考えていませんが、それを実行する能力があるかもしれません)です。

于 2012-12-06T23:18:46.640 に答える
0

必要なのはビット単位または集計関数だと思います。また、Oracle が提供しています ( http://docs.oracle.com/cd/E17952_01/refman-5.1-en/group-by-functions.html#function_bit-orを参照)。

値を BIGINT に変換する必要があります。これは、文字列が 64 ビット未満であることを前提としています。

select t1_id, cast(bit_or(cast(bin_str as bigint)) as varchar(255))
from table2
group by t1_id
于 2012-12-05T17:19:55.243 に答える