Я собираюсь угнать ответ OMG, чтобы четко объяснить проблему и решение.
Ваш первоначальный запрос
WITH q AS (SELECT * FROM iris )
SELECT *
FROM q
WHERE ROWNUM BETWEEN 10 and 150
В любом случае, как говорит OMG, это(хороший) синтаксический сахар для:
SELECT *
FROM (SELECT * FROM iris )
WHERE ROWNUM BETWEEN 10 and 150
Проблема довольно проста.ROWNUM - это виртуальный столбец, который применяется к результирующему набору на уровне, где ROWNUM встречается только .
Короче говоря, этот SQL совпадает с:
SELECT * FROM iris WHERE ROWNUM BETWEEN 10 and 150
который не возвращает строк, так как он завершается неудачно в первом тесте (каждый возможный rownum 1 не проходит тест предложения WHERE, поэтому ROWNUM 1 никогда не будет, не говоря уже о ROWNUM 10).Это не очень интуитивно понятно, но именно так оно и работает.
Решение этого (предоставлено OMG) состоит в том, чтобы преобразовать ROWNUM в столбец во внутреннем выделении ПЕРЕД созданием фильтра для ROWNUM.Я добавил порядок в SQL, поскольку это довольно типично.
SELECT x.*
FROM (SELECT t.*,
ROWNUM AS rn
FROM iris t
ORDER BY something_on_iris ) x
WHERE x.rn >= 10
AND x.rn <= 150
Я подозреваю, это то, что вы пытались сделать с помощью предложения WITH?Важным моментом является преобразование ROWNUM в rn во внутреннем выборе - на уровне ниже вашего фильтра.
Примечание: Oracle распознает этот подход - он не выполняет полное сканирование/ sort на радужной оболочке, но получает первые N соответствующих записей (вы увидите STOPKEY в плане объяснения).