将 TOP 1 相关子查询从 SQL Server 翻译到 Oracle
Posted
技术标签:
【中文标题】将 TOP 1 相关子查询从 SQL Server 翻译到 Oracle【英文标题】:Translate TOP 1 correlated subquery from SQL Server to Oracle 【发布时间】:2013-02-11 08:17:02 【问题描述】:如何在 Oracle 中执行基于 ORDER BY
子句返回第一个匹配行的相关子查询?我正在尝试从执行此操作的 SQL Server 转换查询。
作为记录,我需要坚持(大部分)SQL-92 语法。分析函数根本不应该用,我需要尽量减少非标准SQL的使用。 TOP 1 ... ORDER BY
是 SQL Server 专有的,我正在努力将其转换为 rownum
。
注意:已经指出此特定查询不需要TOP/LIMIT/rownum
,因为它在语义上等同于使用Min()
,因为我们只需要一列。但我仍然会感激并奖励任何有关如何按所述执行翻译的帮助——因为我想更好地学习 Oracle。
这是 SQL Server 查询(和 SqlFiddle for it):
SELECT
D.StartDate,
(
SELECT TOP 1 E.EndDate
FROM dbo.Dates E
WHERE
E.EndDate >= D.EndDate
AND NOT EXISTS (
SELECT *
FROM dbo.Dates E2
WHERE
E.StartDate < E2.StartDate
AND E.EndDate > E2.StartDate
)
ORDER BY
E.EndDate,
E.StartDate DESC
) EndDate
FROM
dbo.Dates D
WHERE
NOT EXISTS (
SELECT *
FROM dbo.Dates D2
WHERE
D.StartDate < D2.EndDate
AND D.EndDate > D2.EndDate
);
这是我尝试过的。我受到了阻碍,因为我在 D.EndDate
外部引用上遇到错误。
ORA-00904: "D"."ENDDATE": 无效标识符
但是有什么问题呢? SELECT
子句中的相关子查询应该可以访问所有外部表数据。我不知道下一步该去哪里。 (还有the SqlFiddle for this)。
SELECT
D.StartDate,
(
SELECT *
FROM (
SELECT E.EndDate
FROM Dates E
WHERE
E.EndDate >= D.EndDate
AND NOT EXISTS (
SELECT *
FROM Dates E2
WHERE
E.StartDate < E2.StartDate
AND E.EndDate > E2.StartDate
)
ORDER BY
E.EndDate,
E.StartDate DESC
)
WHERE rownum = 1
) EndDate
FROM
Dates D
WHERE
NOT EXISTS (
SELECT *
FROM Dates D2
WHERE
D.StartDate < D2.EndDate
AND D.EndDate > D2.EndDate
);
【问题讨论】:
在this article 中,Tom 说:“ANSI SQL 的表引用(相关名称)的范围只有一层”(我不知道如何解决您的问题,抱歉)。跨度> 你为什么要避免分析函数? @Chris 这有关系吗?这是我必须解决的问题。 @Mat 我考虑过但拒绝了,因为 SQL Server 在更深的引用方面没有问题。谢谢你的提示。我会尝试想办法解决这个问题。事实上,我希望尝试使用嵌套派生表。 【参考方案1】:我可能遗漏了一些东西,但是你能不能不使用MIN
而不是TOP 1 ... ORDER BY
,因为你是按EndDate、StartDate DESC 排序的,并且只选择了EndDate,开始日期与排序无关,它是仅当您有 2 个相同的结束日期时才考虑,但由于您只选择结束日期,因此使用两个(或多个结束日期)中的哪一个并不重要:
SELECT D.StartDate,
( SELECT MIN(E.EndDate)
FROM Dates E
WHERE E.EndDate >= D.EndDate
AND NOT EXISTS
( SELECT 1
FROM Dates E2
WHERE E.StartDate < E2.StartDate
AND E.EndDate > E2.StartDate
)
) EndDate
FROM Dates D
WHERE NOT EXISTS
( SELECT 1
FROM Dates D2
WHERE D.StartDate < D2.EndDate
AND D.EndDate > D2.EndDate
);
Example on SQL Fiddle
【讨论】:
你说得对。我只能恳求它已经过了午夜...... :) 相同结束日期的 StartDate 问题对于NOT EXISTS
E2 部分确实很重要。事实上,我仍然不确定我是否 100% 正确......但无论如何,感谢您解决这个特殊问题。无论如何,关于如何在 Oracle 中完成这种类型的相关子查询有什么想法吗?
如果不使用分析函数,我将无法做到这一点,尽管我从未真正使用过 Oracle,因此我可能会遗漏一些技巧。这是我在放弃之前所得到的……sqlfiddle.com/#!4/2e766/40以上是关于将 TOP 1 相关子查询从 SQL Server 翻译到 Oracle的主要内容,如果未能解决你的问题,请参考以下文章
带有相关子查询的 While 循环的 SQL Server 性能调整
为啥此相关子查询在 Oracle 和 SQL Server 中的工作方式不同