First() 函数使用啥顺序?
Posted
技术标签:
【中文标题】First() 函数使用啥顺序?【英文标题】:What order is used by First() function?First() 函数使用什么顺序? 【发布时间】:2012-11-30 18:59:37 【问题描述】:为什么以下两个查询返回相同的结果?
SELECT FIRST(score) FROM (SELECT score FROM scores ORDER BY score ASC)
SELECT FIRST(score) FROM (SELECT score FROM scores ORDER BY score DESC)
考虑到我手动指定子查询的顺序,这很令人困惑。
【问题讨论】:
【参考方案1】:子查询中结果的顺序是无关紧要的,除非您在子查询中使用 TOP,而您在这里没有这样做。大多数 SQL 变体不允许这种语法——例如,在子查询中使用 ORDER BY 会在 SQL Server 中引发错误。
您的***查询没有 ORDER BY,因此在 that 查询的上下文中未定义 FIRST 或 TOP 1 的概念。
在reference docs,微软声明(强调我的):
因为记录通常不会按特定顺序返回(除非 查询包括一个 ORDER BY 子句),这些返回的记录 函数将是任意的。
【讨论】:
我没有访问权限在这里进行测试,您可能对 FIRST() 函数是正确的。我的回答的“肉”是第一段——子查询中的 ORDER BY 是无关紧要的,并且在大多数方言中都是错误的。我将编辑我的回复。 但是包含 Order By 子句要求 Order By 中的所有字段也都在聚合表达式中。但是,如果 Order By 包含多个字段,则将这些字段放入聚合函数或 Group By 子句本质上会破坏 First() 的聚合行为,因为它为所有字段的唯一组合生成了多行。所以 First() 函数仅在对 same, single 字段进行排序时才有用……但它等效于 Min() 和 Max() 函数。因此,答案对于原始问题来说已经足够了,但并不普遍适用。【参考方案2】:直接回答问题:
Access 会忽略大多数子查询中的ORDER BY
子句。我相信(但无法证明)这是由于查询优化器中的错误/限制,尽管它没有在任何地方记录(我可以找到)。我已经使用 Access 2007 和 Access 2016 测试了很多 SQL 来得出这个结论。
使示例按预期工作:
将TOP 100 PERCENT
添加到子查询中:
SELECT FIRST(score) FROM (SELECT TOP 100 PERCENT score FROM scores ORDER BY score ASC)
SELECT FIRST(score) FROM (SELECT TOP 100 PERCENT score FROM scores ORDER BY score DESC)
何时使用First
/Last
而不是Max
/Min
:
当您想要使用这种方法而不是更简单的 Min
和 Max
聚合函数时,一个很好的例子是当您想要来自同一记录的另一个字段时,例如,如果基础 scores
表还举行了name
s玩家和round
s游戏,你可以在每个round
中获得最佳和最差玩家的name
和score
这样:
SELECT
round, FIRST(name) AS best, FIRST(score) AS highscore, LAST(name) AS worst, LAST(score) AS lowscore
FROM
(SELECT TOP 100 PERCENT * FROM scores ORDER BY score DESC)
GROUP BY
round
【讨论】:
但是SELECT TOP 1 * FROM scores ORDER BY score ASC
不是更容易吗?我从来没有找到 First() 的真正应用,除了可能在“只给我任何价值,我不需要聚合”的情况下,例如在一些交叉表查询中。
@Andre 如果你的意思是在子查询中,是的,但我倾向于选择TOP 100 PERCENT
,因为这也适用于外部查询中有GROUP BY
子句的一般情况,即我想要每个组中的 First
值,而不仅仅是整个查询中的第一个值。我唯一一次使用First
是我通常使用分析/窗口函数(如我的上一个示例)但Access 不支持它们的地方。另请注意,Access 中的 TOP 1
实际上返回多行,例如如果有多个玩家得分相同。
实际上我的意思是替换整个查询。但是——还要注意,Access 中的 TOP 1 实际上返回多行相同的值——我不知道这一点:-o。我想我只将它与唯一/关键列一起使用。【参考方案3】:
您的陈述是SELECT Min(Score) FROM Scores
和SELECT Max(Score) FROM Scores
的完美功能等价物。
如果您真的想检索第一个和最后一个分数,您将需要一个 AutoNumber 或一个 DateTime 字段来指示输入顺序。然后你可以查询:
SELECT First(Score), Last(Score) FROM Scores ORDER BY MySortKey
如果您坚持自己的问题,正确的语法应该是SELECT FIRST(score) FROM (SELECT score FROM scores) ORDER BY score ASC
,
或者,简化后,SELECT FIRST(score) FROM scores ORDER BY score ASC
【讨论】:
@HansUp:该代码用于说明其前面的段落。我编辑了我的回复,将名称 GameID 更改为 MySortKey。显然,它需要在表中具有该名称的字段或替换SQL语句中的名称... 为什么到目前为止对这个问题的唯一有效回复收到 -1 ? +1:好点。我没有恶意。但除了 Null 的情况,我坚持认为我的答案是好的,而且这个问题在某种程度上毫无意义。以上是关于First() 函数使用啥顺序?的主要内容,如果未能解决你的问题,请参考以下文章
我不明白函数 foo 和 bar 将按啥顺序执行? [复制]