Я ищу, чтобы преобразовать этот запрос SQL Server (T-SQL), который использует крест, применяется к Oracle 11g. Oracle не поддерживает Cross Apply до 12g, поэтому мне нужно найти работу. Идея запроса - для каждого Tab.Name, что = 'Foobar', мне нужно найти имя предыдущей строки с тем же идентификатором, который был указан Tab.Date. (Эта таблица содержит несколько строк для 1 идентификатора с разными именами и датами).Преобразование T-SQL Cross Применить к Oracle
Вот код 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')
Технически, я смог воссоздать этот же функциональность в Oracle с помощью LEFT JOIN и функции LAG():
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 невозможно. В принципе, я хочу изменить порядок операций в подзапросе, чтобы просто отбросить строки для одного идентификатора, отсортировать эти строки, чтобы найти предыдущий, и присоединиться к этому. Любые идеи о том, как настроить его?
TL; DR SQL Server: фильтров, заказы, присоединяется Oracle: заказов, фильтры, присоединяется
Ваш внутренний запрос говорит 't1.Date = t2.Date', а затем' order by t2.Date'. Таким образом, он выбирает случайную строку. – Andomar
@Andomar Это звучит интересно, не могли бы вы рассказать о том, почему это так? – Wjdavis5
@ Wjdavis5: ну, если вы сначала требуете, чтобы все даты были равны определенному значению (например, 't1.Date'), а затем отсортируйте по этому значению, сортировка не будет делать многое. – Andomar