如果我有这样的结构:
CREATE TABLE things (
id,
personA varchar2,
personB varchar2,
attribute ...,
)
我想找到一个给定的属性,如果我的所有东西都至少有一个普通人,我该怎么做呢?
因此,如果我的数据是(并且每个属性可能超过2个):
1, John, Steve, Apple
2, Steve, Larry, Apple
3, Paul, Larry, Orange
4, Paul, Larry, Orange
5, Chris, Michael, Tomato
6, Steve, Larry, Tomato
对于Apple来说,Steve是我的普通人,对于Orange来说,Paul和Larry都是,而对于Tomato,我没有普通人。但是,我不需要一次返回所有这些的查询。我有其中一个属性,需要0,1或2行,具体取决于我的通用性。我一直试图想出一些东西,但不太清楚。
答案 0 :(得分:6)
这会为您提供common person
/ attribute
列表。我针对您的示例数据运行它并获得预期结果。希望它至少指向正确的方向:)
WITH NormNames AS (
SELECT PersonA AS Person, Attribute FROM things
UNION ALL SELECT PersonB AS Person, Attribute FROM things
)
SELECT
Person, Attribute, COUNT(*)
FROM NormNames
GROUP BY Person, Attribute
HAVING COUNT(*) >= 2
答案 1 :(得分:2)
如果你使用的是11gR2,你也可以使用the unpivot
operator来避免自我加入:
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.
外部查询然后执行一个简单的组。
答案 2 :(得分:1)
这是一种方法。
它通过交叉连接到一个数字列表来实现一个unpivot方法(你可以使用Alex使用的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;