Select 一行有几个聚合 function-based 条件没有子查询
Select one row with several aggregate function-based conditions without subquery
我不确定是否有比 user order by 和 rownum(在 Oracle 中)更优雅的方法来解决这个问题,但这里是:
我有这个table(称为获胜者):
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
house 表示 sq.m 中的房屋大小。
我需要一个查询(没有子查询),它将找到一个 "winner"(名称,但行可以包含更多列)。 "winner" 的定义如下:
- 薪水最低
- (在平局的情况下:)拥有最小的房子
- (如果是另一个平局:)拥有最多的孩子。
在此示例中,获胜者是 Joe,他的收入为 2000,房屋面积为 45,有 4 个孩子。
唯一的方法(它有一个非常简单但有效的代码,仅包含索引,并且仍然有一种子查询(内联),即有另一个 select)是:
select *
from
(select name
from winner
order by salary, house, kids desc)
where rownum = 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>
在早期版本的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 所提到的,在 Oracle 12c+ 中还有一个更好的方法使用 fetch first 1 row only
。并且,还有另一种使用 first_value()
和 select distinct
的方法。这些都没有提供关系解决方案。
我不确定是否有比 user order by 和 rownum(在 Oracle 中)更优雅的方法来解决这个问题,但这里是:
我有这个table(称为获胜者):
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
house 表示 sq.m 中的房屋大小。
我需要一个查询(没有子查询),它将找到一个 "winner"(名称,但行可以包含更多列)。 "winner" 的定义如下:
- 薪水最低
- (在平局的情况下:)拥有最小的房子
- (如果是另一个平局:)拥有最多的孩子。
在此示例中,获胜者是 Joe,他的收入为 2000,房屋面积为 45,有 4 个孩子。
唯一的方法(它有一个非常简单但有效的代码,仅包含索引,并且仍然有一种子查询(内联),即有另一个 select)是:
select *
from
(select name
from winner
order by salary, house, kids desc)
where rownum = 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>
在早期版本的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 所提到的,在 Oracle 12c+ 中还有一个更好的方法使用 fetch first 1 row only
。并且,还有另一种使用 first_value()
和 select distinct
的方法。这些都没有提供关系解决方案。