SQL - 如何选择具有最大值列的行

Abh*_*hek 37 sql oracle

date                 value

18/5/2010, 1 pm        40
18/5/2010, 2 pm        20
18/5/2010, 3 pm        60
18/5/2010, 4 pm        30
18/5/2010, 5 pm        60
18/5/2010, 6 pm        25 
Run Code Online (Sandbox Code Playgroud)

我需要查询具有max(value)的行(即60).所以,这里我们得到两行.从那时起,我需要当天最低时间戳的行(即2010年5月18日,下午3点 - > 60)

Suj*_*jee 50

TOP,LIMIT,ROWNUM等关键字依赖于数据库.请阅读本文以获取更多信息.

http://en.wikipedia.org/wiki/Select_(SQL)#Result_limits

Oracle:可以使用ROWNUM.

select * from (select * from table 
order by value desc, date_column) 
where rownum = 1;
Run Code Online (Sandbox Code Playgroud)

更具体地回答这个问题:

select high_val, my_key
from (select high_val, my_key
      from mytable
      where something = 'avalue'
      order by high_val desc)
where rownum <= 1
Run Code Online (Sandbox Code Playgroud)

  • +1对于这个问题,我建议使用ROWNUM查询.Oracle非常好地优化了这些类型的查询(即使它需要排序,它实际上并不对整个表进行排序 - 它只是在扫描表时保持最顶行) - 并且使用适当的索引它甚至不会必须这样做. (4认同)

Jef*_*emp 29

分析!这样可以避免两次访问表:

SELECT DISTINCT
       FIRST_VALUE(date_col)  OVER (ORDER BY value_col DESC, date_col ASC),
       FIRST_VALUE(value_col) OVER (ORDER BY value_col DESC, date_col ASC)
FROM   mytable;
Run Code Online (Sandbox Code Playgroud)

  • 从纯粹的教育观点来看,我有兴趣看看它有什么样的性能差异.从Toms asktom.oracle网站我了解到使用FIRST_VALUE会产生大量开销.您是否有可能指导我比较它们的一些性能结果? (3认同)

Ter*_*lis 8

答案是添加一个having子句:

SELECT [columns]
FROM table t1
WHERE value= (select max(value) from table)
AND date = (select MIN(date) from table t2 where t1.value = t2.value)
Run Code Online (Sandbox Code Playgroud)

这应该工作,并摆脱在日期子句中有一个额外的子选择的必要性.

  • 嗯...你还有一个子选择 - 事实上,其中两个。 (2认同)

Rob*_*ijk 7

SQL> create table t (mydate,value)
  2  as
  3  select to_date('18/5/2010, 1 pm','dd/mm/yyyy, hh am'), 40 from dual union all
  4  select to_date('18/5/2010, 2 pm','dd/mm/yyyy, hh am'), 20 from dual union all
  5  select to_date('18/5/2010, 3 pm','dd/mm/yyyy, hh am'), 60 from dual union all
  6  select to_date('18/5/2010, 4 pm','dd/mm/yyyy, hh am'), 30 from dual union all
  7  select to_date('18/5/2010, 5 pm','dd/mm/yyyy, hh am'), 60 from dual union all
  8  select to_date('18/5/2010, 6 pm','dd/mm/yyyy, hh am'), 25 from dual
  9  /

Table created.

SQL> select min(mydate) keep (dense_rank last order by value) mydate
  2       , max(value) value
  3    from t
  4  /

MYDATE                   VALUE
------------------- ----------
18-05-2010 15:00:00         60

1 row selected.
Run Code Online (Sandbox Code Playgroud)

问候,Rob.

  • 真正.而且合乎逻辑,因为要确定某些东西是最大值,你必须全部访问它们,或者像索引一样预先订购它们. (4认同)

car*_*rse 6

从技术上讲,这与@Sujee 的答案相同。它还取决于您的 Oracle 版本是否有效。(我认为这种语法是在 Oracle 12 中引入的??)

SELECT *
FROM   table
ORDER BY value DESC, date_column ASC
FETCH  first 1 rows only;
Run Code Online (Sandbox Code Playgroud)

正如我所说,如果您深入了解引擎盖,我认为此代码是由 Oracle Optimizer 在内部解压缩的,读起来就像 @Sujee 的一样。然而,我对漂亮的编码很着迷,select没有充分理由的嵌套语句不符合美观!!:-P