5

我希望将这个使用交叉应用的 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:订单、过滤器、连接

4

1 回答 1

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
于 2015-02-24T09:13:15.553 回答