Oracle 11g SQL查询如何获取多列查询结果中某一列的唯一值

27

给定一个包含人员、他们的母语和其他列C3...C10的表A,请构造一个查询语句,以选择每种语言中一行的所有列。

表A

PERSON  LANGUAGE   ...
bob      英语
john     英语
vlad     俄语
olga     俄语
jose     西班牙语

期望结果

PERSON  LANGUAGE   ...
bob      英语
vlad     俄语
jose     西班牙语

对于我来说,每种语言中哪一行成为结果并不重要。在上面的结果中,我选择了每种语言最低的行号。

6个回答

47

Eric Petroelje几乎就做对了:

SELECT * FROM TableA
WHERE ROWID IN ( SELECT MAX(ROWID) FROM TableA GROUP BY Language )

注意:使用ROWID(行唯一标识符),而不是ROWNUM(它给出结果集中的行号)


4
+1,好的发现!- 我已经离开Oracle世界太久了。 - Eric Petroelje
它可以工作,但这是一个自连接 - 分析函数将以更高效的方式完成相同的工作。 - Jeffrey Kemp

13

这样做会更有效率,并且您可以控制它用于选择值的顺序:

SELECT DISTINCT
       FIRST_VALUE(person)
          OVER(PARTITION BY language
               ORDER BY person)
      ,language
FROM   tableA;

如果您真的不关心每种语言选择哪个人,那么可以省略 ORDER BY 子句:

SELECT DISTINCT
       FIRST_VALUE(person)
          OVER(PARTITION BY language)
      ,language
FROM   tableA;

2
这个能否改为同时选择其他几列的第一个值呢?我在问题中提到了它们作为“由C3...C10表示的其他列...”。谢谢! - Ian Cohen
2
从tableA中选择不同的FIRST_VALUE(colA) OVER (PARTITION BY x), FIRST_VALUE(colB) OVER (PARTITION BY x), ... - Jeffrey Kemp

9

我的Oracle有点生疏,但我认为这个方法可以解决问题:

SELECT * FROM TableA
WHERE ROWID IN ( SELECT MAX(ROWID) FROM TableA GROUP BY Language )

你能对不在SELECT列表中的列进行GROUP BY吗? - tekBlues
@tekBlues - 当然可以,为什么不呢? :) - Eric Petroelje
@Eric Petroelje:不幸的是,这在Oracle中行不通。rownum伪列是在select之后计算的。因此,假设内联查询返回行(2,4,5):外部查询将永远不会返回任何行,因为选择的第一行始终是rownum = 1,这将无法满足{rownum in (2,4,5)}。 - Vincent Malgrat
@Vincent - 对不起,我应该使用ROWID而不是ROWNUM。已经更正了我的答案以反映这一点。 - Eric Petroelje

2

我会在子查询中使用RANK()函数,然后只提取排名为1的行。

select person, language
from
( 
    select person, language, rank() over(order by language) as rank
    from table A
    group by person, language
)
where rank = 1

0
select person, language     
from table A     
group by person, language  

将返回唯一的行


0
为了效率,您希望只访问一次数据,就像Harper一样。但是您不想使用rank(),因为它会给您带来并列的结果,而且您想按语言分组而不是按语言排序。然后,您想添加一个order by子句来区分行,但是您不想实际排序数据。为了实现这一点,我会使用"order by null"。例如:
count(*) over (group by language order by null)

Scott,这里不能使用“group by”,分析查询的语法是“partition by”。你也可以使用“row_number()”代替“count(*)”(可能更易读?) - Vincent Malgrat
这就是我随口乱打的下场。而你两点都说对了。 - Scott Swank

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接