我希望将使用交叉应用的SQL Server(T-SQL)查询转换为Oracle 11g。 Oracle在12g之前不支持Cross Apply,因此我必须找到解决方法。查询背后的想法是每个Tab.Name =' Foobar',我需要找到具有由Tab.Date排序的相同ID的前一行的名称。 (此表包含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语句对它们进行过滤。该表有数百万条记录,因此对于EACH ID这样做是不可行的。基本上,我想更改子查询中的操作顺序,只需拉回单个ID的行,对这些行进行排序以查找前一行,然后加入。关于如何调整它的任何想法?
TL; DR SQL Server:过滤器,订单,加入 Oracle:订单,过滤器,加入
答案 0 :(得分:0)
您可以使用(id)
row_number()
组的最新行
select *
from tab t1
left join
(
select row_number() over (
partition by id
order by Date desc) as rn
, *
from t2
) t2
on t1.id = t2.id
and t2.rn = 1 -- Latest row per id