SQL - 如何选择具有最大值列的行
Posted
技术标签:
【中文标题】SQL - 如何选择具有最大值列的行【英文标题】:SQL - How to select a row having a column with max value 【发布时间】:2011-02-20 16:58:39 【问题描述】: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
我需要查询具有最大值(值)(即 60)的行。所以,这里我们得到两行。从那开始,我需要当天时间戳最低的行(即 2010 年 5 月 18 日,下午 3 点 -> 60)
【问题讨论】:
谢谢大家。现在,如果日期跨越 10 天,我需要对这 10 天中的每一天进行此查询,从而产生 10 行,每行都有该特定日期的最大值。请协助我。 【参考方案1】: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;
更具体地回答问题:
select high_val, my_key
from (select high_val, my_key
from mytable
where something = 'avalue'
order by high_val desc)
where rownum <= 1
【讨论】:
+1 对于这个问题,我推荐 ROWNUM 查询。 Oracle 很好地优化了这些类型的查询(即,即使它需要排序,它实际上并没有对整个表进行排序 - 它只是在扫描表时保留最上面的行) - 并且使用适当的索引它甚至不会必须这样做。【参考方案2】:分析!这样可以避免访问表两次:
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;
【讨论】:
从纯教育的角度来看,我很想看看这有什么样的性能差异。从 Toms asktom.oracle 网站,我了解到使用 FIRST_VALUE 会产生大量开销。您是否可以指导我比较它们的一些性能结果? 如果您在 (value_col, date_col) 上有一个索引,您会发现 Oracle 在使用 Sujee 的查询时会做得很好,因为它将使用COUNT STOPKEY
优化。
它避免了两次扫描表,但它为每一行计算 first_value 列,然后 distinct 将它们全部丢弃,但只有一个。比大多数其他答案更好,但聚合是这里的方法。
是的。 Sujee 击败了我,获得了更好的 ROWNUM 解决方案 :)【参考方案3】:
答案是加一个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)
这应该可以工作,并且无需在日期子句中添加额外的子选择。
【讨论】:
HAVING 子句中的任何非聚合都需要成为 GROUP BY 子句的一部分 好点。我在sybase上测试了我的,它可以让你摆脱它。我修改了答案以适应所需的数据库 嗯...您仍然有一个子选择 - 实际上,其中有两个。 感谢您的反馈,是的,有两个,但标准的替代方法是AND date = select min(date) from table where value = (select max(value) from table))
。我参考 J 布鲁克斯的答案(比这个答案高 3 个)作为证据。通过引用前一个子选择的已经获得的值,您可以保存 1 级嵌套
啊,我明白你现在在说什么了。 ...当然,所有的子选择都是不必要的:)【参考方案4】:
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.
问候, 抢。
【讨论】:
很好,但 Oracle 仍会进行全面扫描 - 不幸的是,它无法应用 COUNT STOPKEY 优化:( 是的。并且合乎逻辑,因为要确定某些东西是最大值,您必须全部访问它们,或者像在索引中一样预先订购它们。【参考方案5】:从技术上讲,这与@Sujee 的答案相同。它还取决于您的 Oracle 版本是否有效。 (我认为这种语法是在 Oracle 12 中引入的??)
SELECT *
FROM table
ORDER BY value DESC, date_column ASC
FETCH first 1 rows only;
正如我所说,如果您深入了解,我认为这段代码是由 Oracle 优化器在内部解压缩的,读起来像 @Sujee 的。然而,我是一个漂亮的编码的傻瓜,没有充分理由嵌套select
语句不符合美丽! :-P
【讨论】:
【参考方案6】:在甲骨文中:
这会根据范围获取表中max(high_val)的key。
select high_val, my_key
from (select high_val, my_key
from mytable
where something = 'avalue'
order by high_val desc)
where rownum <= 1
【讨论】:
【参考方案7】:在 Oracle 数据库中:
create table temp_test1 (id number, value number, description varchar2(20));
insert into temp_test1 values(1, 22, 'qq');
insert into temp_test1 values(2, 22, 'qq');
insert into temp_test1 values(3, 22, 'qq');
insert into temp_test1 values(4, 23, 'qq1');
insert into temp_test1 values(5, 23, 'qq1');
insert into temp_test1 values(6, 23, 'qq1');
SELECT MAX(id), value, description FROM temp_test1 GROUP BY value, description;
Result:
MAX(ID) VALUE DESCRIPTION
-------------------------
6 23 qq1
3 22 qq
【讨论】:
【参考方案8】:最简单的答案是
--建立一个名为“t1”的测试表
create table t1
(date datetime,
value int)
-- 加载数据。 -- 注意:日期格式与问题中不同
insert into t1
Select '5/18/2010 13:00',40
union all
Select '5/18/2010 14:00',20
union all
Select '5/18/2010 15:00',60
union all
Select '5/18/2010 16:00',30
union all
Select '5/18/2010 17:00',60
union all
Select '5/18/2010 18:00',25
-- 找到最大数量和最小日期的行。
select *
from t1
where value =
(select max(value) from t1)
and date =
(select min(date)
from t1
where value = (select max(value) from t1))
我知道你可以做“TOP 1”的答案,但通常你的解决方案会变得非常复杂,以至于由于某种原因你不能使用它。
【讨论】:
对于这个要求,Oracle 不需要对同一个表进行三个额外的访问。 额外访问权限?这将与这里的其他一些执行计划相同,看起来他们做得更少......但可读性较差。而且我知道 Oracle 没有 TOP 命令。【参考方案9】:你可以使用这个功能,ORACLE DB
public string getMaximumSequenceOfUser(string columnName, string tableName, string username)
string result = "";
var query = string.Format("Select MAX (0)from 1 where CREATED_BY = 2", columnName, tableName, username.ToLower());
OracleConnection conn = new OracleConnection(_context.Database.Connection.ConnectionString);
OracleCommand cmd = new OracleCommand(query, conn);
try
conn.Open();
OracleDataReader dr = cmd.ExecuteReader();
dr.Read();
result = dr[0].ToString();
dr.Dispose();
finally
conn.Close();
return result;
【讨论】:
以上是关于SQL - 如何选择具有最大值列的行的主要内容,如果未能解决你的问题,请参考以下文章
选择具有最大值的行,并结合WHERE。 MAX和CAST,在spark.sql中