Oracle SQL,在 SELECT 标头中的子查询中返回唯一(最大)行(在 FROM、WHERE 之前)
Posted
技术标签:
【中文标题】Oracle SQL,在 SELECT 标头中的子查询中返回唯一(最大)行(在 FROM、WHERE 之前)【英文标题】:Oracle SQL, return unique (max) row in subquery in SELECT header (before FROM, WHERE) 【发布时间】:2016-01-24 22:33:49 【问题描述】:我正在 Oracle 服务器上通过 Business Objects 运行 SQL。我有以下代码(简化),有时会运行:
SELECT
a.col1,
a.col2,
a.date1,
(
SELECT
b.date2
FROM
tbl b
WHERE
b.ID = a.ID
AND
b.date2 >= a.date1-60
) AS SUBDATE
FROM
tbl a
WHERE
a.col1 = 'foo'
AND
a.col2 = 'bar'
AND
a.date1 = '#somedate#'
如您所见,SELECT 子句中有一个子查询,我想返回一个值:b.date2。这确实有效……有时。但是,如果 b.ID 返回 多个 记录,其中 date2 在 date1 的最后 60 天内,则查询失败。
我想要做的是将子查询的输出限制为 date2 的单个最新值。我尝试了各种各样的事情:MAX、LIMIT 1、DISTINCT……但是 SQL 无法编译,告诉我我有错误。例如,以下 TOP 1 会产生错误提示“FROM 关键字未在预期位置找到”:
(
SELECT
TOP 1 b.date2
FROM
tbl b
WHERE
b.ID = a.ID
AND
b.date2 >= a.date1-60
) AS SUBDATE
以下 ORDER BY/LIMIT 会产生错误提示“缺少右括号”:
(
SELECT
b.date2
FROM
tbl b
WHERE
b.ID = a.ID
AND
b.date2 >= a.date1-60
ORDER BY b.date2 LIMIT 1
) AS SUBDATE
(仅在上面复制了子查询)。
通过研究这些错误,我看到了关于在主要 WHERE 子句之后的子查询的各种建议;但是没有关于我想要使用它们的方式的子查询。
谁能帮我理解为什么我会出错,正确的方法应该是做什么?
谢谢。
【问题讨论】:
您在 Oracle 手册中的哪个位置找到了TOP 1
或LIMIT 1
?
SELECT MAX(b.date2) FROM
应该可以工作。您也许可以用MAX OVER
或LAG OVER
替换它...
dnoeth - 是的,谢谢!我已经在整个 SELECT 子查询之外尝试了 Max(),但没有在里面尝试:) 马:老实说,我没有 Oracle 手册——我从来没有想过 Oracle 可以有一种 SQL 形式所以与可能不包含 TOP 和 LIMIT 等标准命令的任何其他内容不同。
TOP
和 LIMIT
都不是标准 SQL :-)
dnoeth - 给我的消息!谢谢你。作为一个 SQL n00b,我必须通过实验和失败来学习,并在网上查找。那里有很多文档,但还没有向我明确说明什么是或不是“标准”SQL(直到最近我才知道有不止一种)。 :)
【参考方案1】:
在这种情况下,Oracle 可能会很麻烦(除非您使用的是 Oracle 12)。一种方法使用keep
。但是,在您的情况下,max()
就足够了:
SELECT . . .
(SELECT MAX(b.date2)
FROM tbl b
WHERE b.ID = a.ID AND
b.date2 >= a.date1 - 60
) AS SUBDATE
. . .
注意:您不需要在子查询中使用date2
上的条件,除非您确实想将结果限制为过去 60 天。
【讨论】:
我真的不明白为什么你不能在这里使用 MAX...+1 来自我。 :)以上是关于Oracle SQL,在 SELECT 标头中的子查询中返回唯一(最大)行(在 FROM、WHERE 之前)的主要内容,如果未能解决你的问题,请参考以下文章
pl/sql 块中的子选择上的 Oracle 8i 动态 SQL 错误