2013-04-11 22 views
0

共同的价值。如果我有这样的结构:甲骨文发现在两个不同的列

CREATE TABLE things (
    id, 
    personA varchar2, 
    personB varchar2, 
    attribute ..., 
) 

而且我想找到,对于一个给定的属性,如果我有我的所有的东西至少1普通的人,我会怎么做呢?

所以,如果我的数据是(而且可能超过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 

对于苹果来说,史蒂夫是我的普通人,对于橙保罗和拉里都是,和番茄我有没有平民百姓。但是,我不需要一次返回所有这些查询的查询。我有这些属性之一,并且需要0,1或2行,具体取决于我具有的通用性。我一直在试图想出一些东西,但无法弄清楚。

+0

您需要一个'SELF JOIN'。如果你不想在一个查询中找到所有的匹配项,那么你可以指定特定的属性作为你的一部分ON表达式,或者随后用WHEN过滤掉。 – 2013-04-11 17:28:53

回答

7

这会给你你的common person/attribute名单。我根据您的样本数据运行它并获得了预期的结果。希望这至少是在正确的方向:)

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将列转换为行。单独运行它可以将原来的六行转换为十二行,将原始的/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. 

外部查询然后做一个简单的组。

1

这里有一种方法。

它通过交叉连接到数字列表(您可以使用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;