在单个查询中从两个表中获取不同的单个列值(不是不同的对)

时间:2015-03-26 21:08:28

标签: sql postgresql outer-join distinct-values

我有两张如下表。一个是一些人的体育人才,另一个是艺术人才。一个人可能没有运动天才可以列出,同样适用于艺术人才。

CREATE TABLE SPORT_TALENT(name varchar(10), TALENT varchar(10));
CREATE TABLE ART_TALENT(name varchar(10), TALENT varchar(10));

INSERT INTO SPORT_TALENT(name, TALENT) VALUES
  ('Steve', 'Footbal')
 ,('Steve', 'Golf')
 ,('Bob'  , 'Golf')
 ,('Mary' , 'Tennnis');

INSERT INTO ART_TALENT(name, TALENT) VALUES
  ('Steve', 'Dancer')
, ('Steve', 'Singer')
, ('Bob'  , 'Dancer')
, ('Bob'  , 'Singer')
, ('John' , 'Dancer');

现在我要列出一个人的运动才能和艺术才能。我想避免重复。但是如果有一个" null"我不介意。在任何输出中。我尝试了以下

select distinct sport_talent.talent as s_talent,art_talent.talent as a_talent
from sport_talent
JOIN art_talent on sport_talent.name=art_talent.name
where (sport_talent.name='Steve' or art_talent.name='Steve');

 s_talent | a_talent 
----------+----------
 Footbal  | Dancer
 Golf     | Singer
 Footbal  | Singer
 Golf     | Dancer

我想避免冗余,需要以下内容(体育人才的独特价值+艺术人才的独特价值)。

 s_talent | a_talent 
----------+----------
 Footbal  | Dancer
 Golf     | Singer

正如在主题中提到的,我不是在寻找不同的组合。但与此同时,如果有一些记录带有" null"一列中的值。我对SQL比较陌生。

3 个答案:

答案 0 :(得分:0)

尝试:

SELECT s_talent, a_talent
FROM (
  SELECT distinct on (talent) talent as s_talent,
        dense_rank() over (order by  talent) as x
  FROM SPORT_TALENT
  WHERE name='Steve'
) x
FULL OUTER JOIN (
  SELECT distinct on (talent) talent as a_talent,
        dense_rank() over (order by  talent) as x
  FROM ART_TALENT
  WHERE name='Steve'
) y
ON x.x = y.x

演示:http://sqlfiddle.com/#!15/66e04/3

答案 1 :(得分:0)

您的查询中没有重复项。查询返回的四个记录中的每一个都是唯一的。这个结果可能不是你想要的,但似乎它的问题不是重复。

答案 2 :(得分:0)

Postgres 9.4

...介绍unnest() with multiple arguments。完全是你想要的,也应该快。 Per documentation:

  

可以使用任意数量调用特殊表函数UNNEST   数组参数,并返回相应数量的列,如   如果分别在每个参数上调用UNNEST(第9.18节)   并使用ROWS FROM构造进行组合。

关于ROWS FROM

SELECT *
FROM   unnest(
         ARRAY(SELECT DISTINCT talent FROM sport_talent WHERE name = 'Steve')
       , ARRAY(SELECT DISTINCT talent FROM art_talent WHERE name = 'Steve')
       ) AS t(s_talent, a_talent);

Postgres 9.3或更早

SELECT s_talent, a_talent
FROM  (
   SELECT talent AS s_talent, row_number() OVER () AS rn
   FROM   sport_talent
   WHERE  name = 'Steve'
   GROUP  BY 1
   ) s
FULL JOIN (
   SELECT talent AS a_talent, row_number() OVER () AS rn
   FROM   art_talent
   WHERE  name = 'Steve'
   GROUP  BY 1
   ) a USING (rn);

类似的先前答案有更多解释:

这类似于@kordirko posted,但使用GROUP BY来获取不同的天赋,在窗口函数之前评估。因此,我们只需要一个row_number(),而不是更昂贵的dense_rank()

关于SELECT查询中的事件序列:

SQL Fiddle.