Если у вас есть много строк, которые удовлетворяют предикатам равенства в столбцах Name
, Size
и PType
, то вы можете включить предикаты диапазона в столбец Area
в свой запрос. Если столбец Area
проиндексирован, это может обеспечить эффективный доступ на основе индекса.
Следующий запрос (написанный с использованием синтаксиса Oracle) использует одну ветвь UNION ALL
, чтобы найти запись с минимальной Area >=
вашей целью, в то время как другая ветвь находит запись с максимальной Area <
вашей целью. Одна из этих двух записей будет той записью, которую вы ищете. Затем вы можете ORDER BY ABS(Area - ?input)
выбрать победителя из этих двух кандидатов. К сожалению, запрос сложный из-за вложенных SELECTS, которые необходимы для обеспечения желаемого приоритета ROWNUM / ORDER BY.
SELECT *
FROM
(SELECT * FROM
(SELECT * FROM
(SELECT * FROM [myTable]
WHERE Name = 'Test' AND Size = 2 AND PType = 'p' AND Area >= ?target
ORDER BY Area)
WHERE ROWNUM < 2
UNION ALL
SELECT * FROM
(SELECT * FROM [myTable]
WHERE Name = 'Test' AND Size = 2 AND PType = 'p' AND Area < ?target
ORDER BY Area DESC)
WHERE ROWNUM < 2)
ORDER BY ABS(Area - ?target))
WHERE rownum < 2
Хорошим индексом для этого запроса будет (Name, Size, PType, Area)
, и в этом случае ожидаемый план выполнения запроса будет основан на двух сканированиях диапазона индекса, каждый из которых вернул одну строку.