Oracle 11G
表2具有T1_ID和表示二进制数
的字符串(BIN_STR)示例:
表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中有没有办法做到这一点?
答案 0 :(得分: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
答案 1 :(得分:0)
在SQL 11g中有几种方法可以做到这一点。这是行动中的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
并计算结果。如果有第三个二进制“0001”,我们想要0101 XOR 1100 = res
然后res XOR 0001
,依此类推。我们只对最终结果感兴趣,所以我们最终可以使用行号来为我们过滤:
10 dimension by (row_number() over (partition by t1_id order by bin_str) rn )
我们也将维持每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 = bin_str [cv() - 1]为null时的15种情况 16然后bin_str [cv()] 17其他强制转换(utl_raw.bit_or(new_bin_str [cv() - 1],bin_str [cv()])为varchar2(16)) 18结束))
所以说的是,对于第一行的每一行(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(没有想到一个但是它也可能有能力做到这一点)。