选择具有多个基于函数的聚合条件的一行,而不使用子查询

时间:2016-05-03 18:54:35

标签: sql oracle sql-order-by aggregate-functions rownum

我不确定是否有更优雅的解决方法,而不是用户订单和rownum(在Oracle中),但是这里有:

我有这张桌子(叫赢家):

Name     Salary     House   Kids
--------------------------------
Barabara 2500.00    40      4
Dale     2000.00    60      3
Aaron    2000.00    45      2
Joe      2000.00    45      4
Jacob    2000.00    50      4
Melissa  2500.00    50      4

房子是指平方米的房屋面积。

我需要一个查询(没有子查询),它会找到一个"赢家" (名称,但行可以有更多列)。 "赢家"定义如下:

  • 获得最低工资
  • (如果是领带:)拥有最小的房子
  • (如果是另一个领带:)拥有最多的孩子。

在此示例中,获胜者为 Joe ,获得2000,房屋大小为45,并且有4个孩子。

唯一的方法(它有一个非常简单但有效的代码只有索引,并且仍然有一种子查询(内联),即有另一个选择)是:

select * 
from 
    (select name 
     from winner
     order by salary, house, kids desc)
where rownum = 1;

如果没有子查询,还有其他方法吗? (也许是聚合函数?)

2 个答案:

答案 0 :(得分:1)

如果您在12c上尝试FETCH FIRST ROW ONLY

有关详细信息,请参阅此文章:https://oracle-base.com/articles/12c/row-limiting-clause-for-top-n-queries-12cr1

示例如下所示:

SELECT val
FROM   rownum_order_test
ORDER BY val DESC
FETCH FIRST 5 ROWS ONLY;

       VAL
----------
        10
        10
         9
         9
         8

5 rows selected.

SQL>

答案 1 :(得分:1)

在早期版本的Oracle中,您可以使用keep

select max(name) keep (dense_rank first order by salary, house, kids desc) as name,
       max(salary) keep (dense_rank first order by salary, house, kids desc) as name,
       max(house) keep (dense_rank first order by salary, house, kids desc) as name,
       max(kids) keep (dense_rank first order by salary, house, kids desc) as name
from rownum_order_test;

如果你想要领带,你也可以尝试:

select listagg(name, ',') keep (dense_rank first order by salary, house, kids desc) as names 
from rownum_order_test;

在使用相关子查询时,此构造非常有用,因为Oracle中的相关子句的作用域有限。请注意,获取值时

正如Bulat所提到的,使用fetch first 1 row only的Oracle 12c +中还有一种更好的方法。而且,还有另一种使用first_value()select distinct的方法。这些都没有为关系提供解决方案。