Sql Oracle在两个不同的列中查找公共值
如果我有这样一个结构:Sql Oracle在两个不同的列中查找公共值,sql,oracle,Sql,Oracle,如果我有这样一个结构: CREATE TABLE things ( id, personA varchar2, personB varchar2, attribute ..., ) 我想找到,对于一个给定的属性,如果我的所有东西至少有一个普通人,我该怎么做 因此,如果我的数据是(每个属性可能超过2个): 对于苹果,史蒂夫是我的普通人,对于橘子,保罗和拉里都是,对于西红柿,我没有普通人。但是,我不需要一个同时返回所有这些内容的查询。我有其中一个属性,需要0、1或2
CREATE TABLE things (
id,
personA varchar2,
personB varchar2,
attribute ...,
)
我想找到,对于一个给定的属性,如果我的所有东西至少有一个普通人,我该怎么做
因此,如果我的数据是(每个属性可能超过2个):
对于苹果,史蒂夫是我的普通人,对于橘子,保罗和拉里都是,对于西红柿,我没有普通人。但是,我不需要一个同时返回所有这些内容的查询。我有其中一个属性,需要0、1或2行,具体取决于我的公共性。我一直在想办法,但还不太清楚。这将为您提供
普通人
/属性
列表。我根据你的样本数据运行了它,得到了预期的结果。希望它至少指向了正确的方向:)
如果您使用的是11gR2,您还可以使用来避免自连接:
select person, attribute
from (
select *
from things
unpivot (person for which_person in (persona as 'A', personb as 'B'))
)
group by person, attribute
having count(*) > 1;
PERSON ATTRIBUTE
---------- ----------
Steve Apple
Paul Orange
Larry Orange
3 rows selected.
或者只针对符合该属性的人,我认为这就是你问题的目的:
select person
from (
select *
from things
unpivot (person for which_person in (persona as 'A', personb as 'B'))
)
where attribute = 'Apple'
group by person, attribute
having count(*) > 1;
PERSON
----------
Steve
1 row selected.
unpivot
将列转换为行。独立运行它将原来的六行转换为十二行,将原来的persona
/personb
列替换为一个person
和一个额外的列,该列指示新行是从哪个列组成的,我们在这里并不关心:
select *
from things
unpivot (person for which_person in (persona as 'A', personb as 'B'));
ID ATTRIBUTE W PERSON
---------- ---------- - ----------
1 Apple A John
1 Apple B Steve
2 Apple A Steve
2 Apple B Larry
3 Orange A Paul
3 Orange B Larry
4 Orange A Paul
4 Orange B Larry
5 Tomato A Chris
5 Tomato B Michael
6 Tomato A Steve
6 Tomato B Larry
12 rows selected.
然后外部查询执行一个简单的分组。这里有一个方法
它通过交叉连接到一个数字列表(您可以使用Alex使用的unpivot方法)来实现unpivot方法,然后连接结果集,希望通过哈希连接来增加优点
with
row_generator as (
select 1 counter from dual union all
select 2 counter from dual),
data_generator as (
select
attribute,
id ,
case counter
when 1 then persona
when 2 then personb
end person
from
things,
row_generator)
select
t1.attribute,
t1.person
from
row_generator t1,
row_generator t2
where
t1.attribute = t2.attribute and
t1.person = t2.person and
t1.id != t2.id;
您需要一个
自联接
。如果不希望在一个查询中包含所有匹配项,则可以将特定属性指定为ON
表达式中的的一部分,或者在之后使用WHEN将其过滤掉。
select *
from things
unpivot (person for which_person in (persona as 'A', personb as 'B'));
ID ATTRIBUTE W PERSON
---------- ---------- - ----------
1 Apple A John
1 Apple B Steve
2 Apple A Steve
2 Apple B Larry
3 Orange A Paul
3 Orange B Larry
4 Orange A Paul
4 Orange B Larry
5 Tomato A Chris
5 Tomato B Michael
6 Tomato A Steve
6 Tomato B Larry
12 rows selected.
with
row_generator as (
select 1 counter from dual union all
select 2 counter from dual),
data_generator as (
select
attribute,
id ,
case counter
when 1 then persona
when 2 then personb
end person
from
things,
row_generator)
select
t1.attribute,
t1.person
from
row_generator t1,
row_generator t2
where
t1.attribute = t2.attribute and
t1.person = t2.person and
t1.id != t2.id;