2009-07-13 81 views
4

一个相当复杂的SQL查询我工作让我思考(ANSI)SQL的限制:检索最大/最小记录

有没有一种方法来检索记录是最大或最小相对于一任意排序?

换句话说:

鉴于这样的查询:

SELECT * FROM mytable WHERE <various conditions> ORDER BY <order clause> 

是有可能写的是(通过变换顺序条款到别的可能)只返回第一行查询?

我知道你可以做到这一点使用LIMIT(MySQL的)/ ROWNUM(甲骨文)或类似的,但是这不是标准的SQL。我也知道你可以通过在子查询中获取你感兴趣的最大/最小值(使用MIN()/ MAX())来做到这一点,然后在你的主要SELECT中使用该结果作为标准,即:

SELECT * FROM mytable WHERE <various conditions> AND myMaxColumn=(
    SELECT MAX(myMaxColumn) FROM mytable WHERE <various conditions> 
) 

但是,这只能如果我想通过一个单一的列进行排序。我没有办法将其推广到多列(除了嵌套上述解决方案,但这意味着当由n个coluns排序时,会有2^n个SELECT)。

那么,有没有标准SQL更好的方式比嵌套多个子选择?

一个相关的问题是Create a SQL query to retrieve most recent records问。然而,问题的答案有建议或者使用LIMIT &的朋友,或者使用子查询与MAX()如上所述,这两者是不是我的问题的解决方案。

+0

注意:刚刚发现了一个类似的问题:http://stackoverflow.com/questions/121387/fetch-the-row-which-has-the-max-value-for-a-column – sleske 2012-03-28 16:01:03

回答

10

SQL:2003定义的窗口功能,其中的一个概念:

SELECT * 
FROM (
     SELECT *, ROW_NUMBER() OVER (ORDER BY col1, col2, col3) AS rn 
     FROM mytable 
     ) q 
WHERE rn = 1 

将返回你这第一条记录。

至于现在,它是由SQL ServerOracle以来Jul 01, 2009支持。但是,通过PostgreSQL 8.4

注意的是,ROW_NUMBER()Oracle比原生的方式效率较低,限制记录(即ROWNUM)。

看到这篇文章在我的博客的性能对比:

SQL:2008提供了一个条款要做到这一点:

SELECT * 
FROM mytable 
ORDER BY 
     col1, col2, col3 
FETCH FIRST 1 ROW ONLY 

,但就目前而言,这个确切语法仅支持DB2AFAIK)。

+0

这适用于数据库实施SQL2003标准。它在很多数据库中都不被支持,包括MySQL和PostgreSQL。这绝对是编写这种查询类型的最简单方法之一。 – LBushkin 2009-07-13 12:08:40

8

如果我理解正确的话,你,我想你正在寻找的OVER子句,可以用来分隔结果集,定义为ANSI SQL 2003标准的一部分。

它在RDBMS平台上的实现并不是很一致。