我希望创建一个将两个表连接在一起的视图。
T1 =
Col1 Col2
AA BB
EE FF
YY ZZ
11 00
T2 =
Col1 Col2 Col3
AA BB 1
AA CC 2
CC BB 3
GG FF 4
GG HH 5
EE HH 6
XX YY 7
XX WW 8
YY RR 9
此视图的规则是基于以下规则的最佳匹配方案:
1. Return Col3 from T2 if T1.Col1 & T1.Col2 = T2.Col1 & T2.Col2
ELSE
2. Return Col3 if T1.Col2 = T2.Col2
ELSE
3. Return Col3 if T1.Col = T2.Col1
ELSE
4. Return NULL
因此,在这些示例中,我希望最终视图包含:
AA BB 1 (Rule 1 match)
EE FF 4 (Rule 2 match)
YY ZZ 9 (Rule 3 match)
11 00 NULL (Rule 4 match)
我遇到的困难是在达到多个规则的情况下(例如,第1和第3行是规则1和2,第4和第6行是规则2和3分别命中的。)
我在这个例子中意识到规则3被多次击中 - 这很好,因为这个想法只有在其他规则不是真的时才会达到规则3,其中应该只产生1个结果(如例3)。
是否有办法建立类似的联合以满足这些级联规则,或者是否需要使用预过滤创建其他视图(例如计数< 2)?
excel中的这个公式将是: = IF(AND(A3 = $ F $ 2,B3 = $ G $ 2)," Rule1",IF((B3 = $ G $ 2),"规则2",IF(( A3 = $ F $ 2),"规则3"," NULL")))
A3 = T2.Col1,B3 = T2.Col2 G2 = T1.Col2,F2 = T1.Col1。
答案 0 :(得分:1)
我这样做:
with t1 as (select 'AA' col1, 'BB' col2 from dual union all
select 'EE' col1, 'FF' col2 from dual union all
select 'YY' col1, 'ZZ' col2 from dual union all
select '11' col1, '00' col2 from dual),
t2 as (select 'AA' col1, 'BB' col2, 1 col3 from dual union all
select 'AA' col1, 'CC' col2, 2 col3 from dual union all
select 'CC' col1, 'BB' col2, 3 col3 from dual union all
select 'GG' col1, 'FF' col2, 4 col3 from dual union all
select 'GG' col1, 'HH' col2, 5 col3 from dual union all
select 'EE' col1, 'HH' col2, 6 col3 from dual union all
select 'XX' col1, 'YY' col2, 7 col3 from dual union all
select 'XX' col1, 'WW' col2, 8 col3 from dual union all
select 'YY' col1, 'RR' col2, 9 col3 from dual),
res as (select t1.col1,
t1.col2,
t2.col3,
case when t1.col1 = t2.col1 and t1.col2 = t2.col2 then 1
when t1.col2 = t2.col2 then 2
when t1.col1 = t2.col1 then 3
end join_level,
min (case when t1.col1 = t2.col1 and t1.col2 = t2.col2 then 1
when t1.col2 = t2.col2 then 2
when t1.col1 = t2.col1 then 3
end) over (partition by t1.col1, t1.col2) min_join_level
from t1
left outer join t2 on (t1.col1 = t2.col1 or t1.col2 = t2.col2))
select col1,
col2,
col3
from res
where join_level = min_join_level
or join_level is null;
COL1 COL2 COL3
---- ---- ----------
11 00
AA BB 1
EE FF 4
YY ZZ 9
IE中。首先进行连接(在这种情况下,t1 left outer join t2 on (t2.col1 = t1.col1 or t2.col2 = t1.col2)
包括t1.col1 = t2.col1 and t1.col2 = t2.col2
)的行,然后根据哪个连接条件优先过滤结果。
这里有一个稍微不同的选择,使用聚合而不是上述答案的分析函数:
with t1 as (select 'AA' col1, 'BB' col2 from dual union all
select 'EE' col1, 'FF' col2 from dual union all
select 'YY' col1, 'ZZ' col2 from dual union all
select '11' col1, '00' col2 from dual),
t2 as (select 'AA' col1, 'BB' col2, 1 col3 from dual union all
select 'AA' col1, 'CC' col2, 2 col3 from dual union all
select 'CC' col1, 'BB' col2, 3 col3 from dual union all
select 'GG' col1, 'FF' col2, 4 col3 from dual union all
select 'GG' col1, 'HH' col2, 5 col3 from dual union all
select 'EE' col1, 'HH' col2, 6 col3 from dual union all
select 'XX' col1, 'YY' col2, 7 col3 from dual union all
select 'XX' col1, 'WW' col2, 8 col3 from dual union all
select 'YY' col1, 'RR' col2, 9 col3 from dual)
select t1.col1,
t1.col2,
min(t2.col3) keep (dense_rank first order by case when t1.col1 = t2.col1 and t1.col2 = t2.col2 then 1
when t1.col2 = t2.col2 then 2
when t1.col1 = t2.col1 then 3
end) col3
from t1
left outer join t2 on (t1.col1 = t2.col1 or t1.col2 = t2.col2)
group by t1.col1,
t1.col2;
COL1 COL2 COL3
---- ---- ----------
11 00
AA BB 1
EE FF 4
YY ZZ 9
N.B。如果碰巧有多个行符合最高优先级的可用连接条件,则这些结果可能会返回不同的结果。第一个查询将返回具有(可能)不同col3的每一行,而第二个查询将返回一行,具有最低可用col3值。
如果包含T2,您希望看到什么:
COL1 COL2 COL3
---- ---- ----------
AA BB 1
AA CC 2
CC BB 3
GG FF 4
GG HH 5
EE HH 6
XX YY 7
XX WW 8
YY RR 9
YY SS 10
第一个查询将为您提供:
COL1 COL2 COL3
---- ---- ----------
11 00
AA BB 1
EE FF 4
YY ZZ 10
YY ZZ 9
第二个查询将为您提供:
COL1 COL2 COL3
---- ---- ----------
11 00
AA BB 1
EE FF 4
YY ZZ 9
答案 1 :(得分:0)
也许这个方法将三个公用表表达式的结果集链接在一起,每个表达式实现一个不同的连接,并检查T1中行的rowid是否已经从成功连接中投射出来:
with
first_join as (
select t1.col1,
t1.col2,
t2.col3,
t1.rowid
from t1 join t2 on t1.col1 = t2.col1 and t1.col2 = t2.col2),
second_join as (
select t1.col1,
t1.col2,
t2.col3,
t1.rowid
from t1 join t2 on t1.col2 = t2.col2
where t1.rowid not in (select rowid from first_join)),
third_join as (
select t1.col1,
t1.col2,
t2.col3,
from t1 join t2 on t1.col1 = t2.col1
where t1.rowid not in (select rowid from first_join union all
select rowid from second_join))
select col1, col2, col3 from first_join union all
select col1, col2, col3 from second_join union all
select col1, col2, col3 from third_join