4

我正在处理的一个相当复杂的 SQL 查询让我想到了(ANSI)SQL 的限制:

有没有办法检索关于任意排序的最大或最小记录?

换句话说:

给定这样的查询:

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

是否可以编写只返回第一行的查询(可能通过将 order 子句转换为其他内容)?

我知道您可以使用 LIMIT (MySQL) / ROWNUM (Oracle) 或类似方法执行此操作,但这不是标准 SQL。

我也知道您可以通过获取您在子查询中感兴趣的最大值/最小值(使用 MIN()/MAX())来做到这一点,然后将该结果用作主 SELECT 中的标准,即:

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

但这仅在我想按单列排序时才有效。我认为没有办法将其推广到多列(除了嵌套上述解决方案,但这意味着在按 n 列排序时有 2^n SELECTs)。

那么在标准 SQL 中有没有比嵌套多个子选择更好的方法呢?

在创建 SQL 查询以检索最新记录中提出了一个相关问题。但是,那里的答案建议使用 LIMIT 和朋友,或者使用带有 MAX() 的子查询,如上所述,这两者都不是我问题的解决方案。

4

2 回答 2

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()inOracle的效率低于限制记录的本地方式(即ROWNUM)。

有关性能比较,请参阅我的博客中的这篇文章:

SQL:2008提供另一个条款来做到这一点:

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

DB2,但就目前而言,只有 ( )支持这种确切的语法AFAIK

于 2009-07-13T12:05:48.853 回答
8

如果我的理解正确,我认为您正在寻找 OVER 子句,它使您能够对结果集进行分区,定义为ANSI SQL 2003标准的一部分。

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

于 2009-07-13T12:06:14.390 回答