0

如果我有这样的结构:

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 行,具体取决于我有什么样的共性。我一直试图想出一些东西,但不能完全弄清楚。

4

3 回答 3

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
于 2013-04-11T17:28:24.070 回答
2

如果您使用的是 11gR2,您还可以使用运算unpivot来避免自加入:

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.

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

于 2013-04-11T17:54:31.743 回答
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;
于 2013-04-11T18:57:09.860 回答