ORA-00904: "PREV_TEMP": 带有 LAG 函数的无效标识符

Posted

技术标签:

【中文标题】ORA-00904: "PREV_TEMP": 带有 LAG 函数的无效标识符【英文标题】:ORA-00904: "PREV_TEMP": invalid identifier with LAG function 【发布时间】:2019-05-24 11:48:42 【问题描述】:

这个查询有什么问题?

它返回: ORA-00904: "PREV_TEMP": invalid identifier

SELECT Id, RecordDate, Temperature, LAG(Temperature) OVER (ORDER BY RecordDate) as prev_temp
FROM Weather
WHERE Temperature > prev_temp;

SQL 架构:

Create table If Not Exists Weather (Id int, RecordDate date, Temperature int)
Truncate table Weather
insert into Weather (Id, RecordDate, Temperature) values ('1', '2015-01-01', '10')
insert into Weather (Id, RecordDate, Temperature) values ('2', '2015-01-02', '25')
insert into Weather (Id, RecordDate, Temperature) values ('3', '2015-01-03', '20')
insert into Weather (Id, RecordDate, Temperature) values ('4', '2015-01-04', '30')

【问题讨论】:

【参考方案1】:

查询的问题在于列别名不能在定义它们的SELECTWHEREFROMGROUP BY 子句中重复使用。这适用于窗口函数,以及其他一切。这是 SQL 中的规则,而不是 Oracle 中的规则(尽管有些数据库放宽了对 GROUP BY 的限制)。

在您的情况下,基本上有两种解决方案,一个子查询和一个 CTE:

WITH w AS (
      SELECT w.*,
             LAG(Temperature) OVER (ORDER BY RecordDate) as prev_temperature
      FROM weather w
     ) 
SELECT Id, RecordDate, Temperature,  prev_temp
FROM w
WHERE Temperature > prev_temp; 

【讨论】:

确实有两个问题。在许多情况下,您可以通过简单地重复 WHERE 子句(或其他子句)中的表达式来解决没有子查询的别名问题。唉,分析函数并非如此——即使没有别名,它们也不能在其他子句中使用(ORDER BY 除外,它在SELECT 之后进行评估)。另请注意,“子查询和 CTE”并不是真正的两个解决方案 - CTE 是“分解的子查询”。 我也怀疑任何数据库都放宽了专门针对GROUP BY 的别名限制。你能推荐一些例子吗?还是你把它和ORDER BY 混在一起了? @mathguy 。 . . mysql(以及由此而来的 MariaDB)、BigQuery、Hive、Postgres(以及由此而来的一堆 Postgres 派生的数据库)。对于非传统数据库来说,这是相当标准的做法。【参考方案2】:

不能直接使用,需要在子查询中使用才能使用解析函数的返回值

SELECT *
  FROM
  (
   SELECT Id, RecordDate, Temperature, 
          LAG(Temperature) OVER (ORDER BY RecordDate) as prev_temp
     FROM Weather
  )
  WHERE Temperature > prev_temp;

【讨论】:

谢谢,这行得通。您能否解释一下为什么我们应该使用子查询以及为什么上面列出的查询不起作用? @raiym 不客气。因为它们是取决于表的相关列的计算列。即它们实际上是结果。 我会说“因为它们是根据表的相关 计算的列”。这确实是问题的中心点;如果计算仅依赖于其他列(在同一行内),则使用 WHERE 中的表达式不会有问题(但是,当然,没有别名 - 必须重复该表达式)。因为分析函数依赖于其他,所以它们不能WHERE 中与SELECT 处于同一级别,即使它们被完整拼写而不是而不是别名。

以上是关于ORA-00904: "PREV_TEMP": 带有 LAG 函数的无效标识符的主要内容,如果未能解决你的问题,请参考以下文章

ORA-00904: "FORMAT": 无效标识符

ORA-00904: "CEILING": ORACLE 11G 中的标识符无效

ORA-00904: "DAYS": 无效标识符

ORA-00904: "pass": 无效的标识符

ORA-00904: "PREV_TEMP": 带有 LAG 函数的无效标识符

SQL 错误:ORA-00904:“GENDER”:无效标识符 00904。00000 -“%s:无效标识符”