Oracle在两个不同的列中找到了共同的价值

时间:2013-04-11 17:20:26

标签: sql oracle

如果我有这样的结构:

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行,具体取决于我的通用性。我一直试图想出一些东西,但不太清楚。

3 个答案:

答案 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;