2013-04-11 4 views
0

Если у меня есть структура вроде этого:Oracle найти общее значение в двух разных колонках

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 

Для Apple, Стив мой обычный человек, для Orange Павел и Ларри есть, и для томата у меня есть нет простых людей. Однако мне не нужен запрос, который возвращает все эти данные одновременно. У меня есть один из этих атрибутов и хочу 0, 1 или 2 строки в зависимости от того, какая у меня общность. Я пытался что-то придумать, но не могу понять.

+0

Вам нужно «САМОЕ ПРИСОЕДИНЕНИЕ». Если вам не нужны все совпадения в одном запросе, вы можете указать конкретный атрибут как часть выражения 'ON' или отфильтровать его с помощью WHEN после этого. –

ответ

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 переводит столбцы в строки. Бег сам по себе преобразует ваши оригинальные шесть рядов в двенадцать, заменяя оригинальные столбцы одним номером 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

Это один из способов.

Он реализует метод univot путем перекрестного соединения с списком чисел (вы можете использовать метод, который не использует Alex), а затем присоединяется к набору результатов, надеюсь, с хеш-соединением для дополнительного добра.

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; 
Смежные вопросы