How do I perform a correlated subquery in Oracle that returns the first matching row based on an ORDER BY clause? I’m trying to translate a query from SQL Server that does this.
For the record, I need to stick to (mostly) SQL-92 syntax. Analytic functions should not be used at all, and I need to minimize the use of nonstandard SQL. TOP 1 ... ORDER BY is proprietary to SQL Server and I’m struggling translating it to rownum.
Note: It has been pointed out that this particular query doesn’t require TOP/LIMIT/rownum since it is semantically equivalent to use Min() as we only want one column. But I would still appreciate, and will reward, any help on how to perform the translation as stated–since I would like to learn Oracle better.
Here’s the SQL Server query (and the 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
);
This is what I’ve tried. I’m stymied because I’m getting an error on the D.EndDate outer reference.
ORA-00904: “D”.”ENDDATE”: invalid identifier
But what’s the problem? A correlated subquery in the SELECT clause should have access to all outer table data. I don’t know where to go next. (And 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
);
I might be missing something, but can you not use
MINinstead ofTOP 1 ... ORDER BY, since you are ordering by EndDate, StartDate DESC, and only selecting EndDate, the start date is not relevant to the sort, it is only considered when you have 2 end dates that are the same, but since you are only selecting end date it doesn’t matter which of the two (or more end dates) are used:Example on SQL Fiddle