是否有函数或运算符或其他简单(r)构造来获取oracle sql中两个元组文字的交集?
考虑以下例子:
有下表
------------------------------
TABLE sometable
------------------------------
id | telephone | mobile | fax
------------------------------
1 | 123 | 456 | 789
给出n个数字的列表{n1,n2,n3,...,n} 找到id,这样:
telephone = n1 or mobile = n1 or fax = n1
or telephone = n2 or mobile = n2 or fax = n2
or telephone = n3 or mobile = n3 or fax = n3
....
or telephone = n or mobile = n or fax = n
两个合理的解决方案是:
1。解决方案1
SELECT id FROM sometable
WHERE
n1 IN (telephone, mobile, fax)
OR n2 IN (telephone, mobile, fax)
OR n3 IN (telephone, mobile, fax)
....
OR n IN (telephone, mobile, fax)
;
2。解决方案2
SELECT id FROM sometable
WHERE
telephone IN (n1, n2, n3, ..., n)
OR mobile IN (n1, n2, n3, ..., n)
OR fax IN (n1, n2, n3, ..., n)
;
但是有一个函数/运算符可以执行以下操作吗?
SELECT id
FROM sometable
WHERE
intersect_function
(
(telephone, mobile, fax),
(n1, n2, n3, ..., n)
)
= TRUE
;
另一种更简单的结构将受到欢迎,考虑到这种情况是较长查询的一部分,具有更多且可能更复杂的条件。
感谢。
答案 0 :(得分:2)
我的想法是通过with
子句将搜索号转换为表格:
然后使用一点regexp技巧,您可以从单行创建每个值一行,并通过in
子句将它们与您的表匹配:
create TABLE sometable
(
id number,
telephone number,
mobile number,
fax number
);
insert into sometable values(1, 123, 456, 789);
insert into sometable values(2, 0, 0, 123);
insert into sometable values(3, 456, 0, 0);
with w(n) as
(
select regexp_substr('123, 456', '\d+', 1, level) n
from dual
connect by regexp_instr('123, 456', '\d+', 1, level) != 0
)
select *
from sometable s, w
where w.n in (s.telephone, s.mobile, s.fax)
;
这符合预期:
ID TELEPHONE MOBILE FAX N
1 123 456 789 123
2 0 0 123 123
1 123 456 789 456
3 456 0 0 456
答案 1 :(得分:1)
通过创建自己的类型和函数,您可以实现与所需SQL非常相似的东西:
SELECT id
FROM sometable
WHERE
intersect_function
(
num_tab(telephone, mobile, fax),
num_tab(123, 456)
) > 0;
首先,您需要声明此类型:
SQL> create type num_tab is table of number;
2 /
Type created.
...而且这个功能:
create or replace function intersect_function
( p_tab1 num_tab
, p_tab2 num_tab
) return number
is
l_intersect num_tab;
begin
l_intersect := p_tab1 multiset intersect p_tab2;
return l_intersect.count;
end;
但是,请注意,通过为每行数据调用函数并且无法使用索引,这可能不是最高性能的解决方案!