2013-04-11 47 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;