我希望将这个使用交叉应用的 SQL Server (T-SQL) 查询转换为 Oracle 11g。Oracle 直到 12g 才支持 Cross Apply,所以我必须找到解决方法。查询背后的想法是对于 = 'Foobar' 的每个 Tab.Name,我需要找到具有相同 ID 的前一行的名称,该 ID 由 Tab.Date 排序。(此表包含 1 个具有不同名称和日期的 ID 的多行)。
这是 T-SQL 代码:
SELECT DISTINCT t1.ID
t1.Name,
t1.Date,
t2.Date as 'PreviousDate',
t2.Name as 'PreviousName'
FROM Tab t1
OUTER apply (SELECT TOP 1 t2.Date,
t2.Name
FROM Tab t2
WHERE t1.Id = t2.Id
ORDER BY t2.Date DESC) t2
WHERE t1.Name = 'Foobar' )
从技术上讲,我能够使用 LEFT JOIN 和 LAG() 函数在 Oracle 中重新创建相同的功能:
SELECT DISTINCT t1.ID
t1.Name,
t1.Date,
t2.PreviousDate as PreviousDate,
t2.PreviousName as PreviousName
FROM Tab t1
LEFT JOIN (
SELECT ID,
LAG(Name) OVER (PARTITION BY ID ORDER BY PreviousDate) as PreviousName,
LAG(Date) OVER (PARTITION BY ID ORDER BY PreviousDate) as PreviousDate
FROM Tab) t2 ON t2.ID = t1.ID
WHERE t1.Name = 'Foobar'
问题在于它执行 Oracle 查询的顺序。它将从 Tab 中拉回所有行,对它们进行排序(因为 LAG 函数),然后在将其连接到主查询时使用 ON 语句将它们过滤掉。该表有数百万条记录,因此对每个 ID 这样做是不可行的。基本上,我想更改子查询中的操作顺序,只为单个 ID 拉回行,对这些行进行排序以找到前一个,然后加入。关于如何调整它的任何想法?
TL;DR SQL Server:过滤器、订单、连接 Oracle:订单、过滤器、连接