這個有點難搜索,所以我在這里問(我在哪里看到了關于 的問題lnnvl())。
我有一個查詢,看起來像:
SELECT *
FROM foo
WHERE foo.bar NOT IN ('X', 'Y')
OR foo.bar IS NULL;
不久前,我了解到lnnvl()并且能夠用以下方法做同樣的事情:
SELECT *
FROM foo
WHERE lnnvl(foo.bar = 'X')
AND lnnvl(foo.bar = 'Y');
這很棒,但在檢查更大的集合時不是很可擴展。你們中的任何人都知道有更清潔的方法嗎?過去,我做過類似的事情:
SELECT *
FROM foo
WHERE nvl(foo.bar, ' ') NOT IN ('X', 'Y')
我很欣賞任何見解!
uj5u.com熱心網友回復:
您的最后一個選項很好,并導致以下filter謂詞
filter(NVL("FOO"."BAR",' ')<>'X' AND NVL("FOO"."BAR",' ')<>'Y')
我沒有看到其他可能性,因為下面的謂詞導致例外
WHERE lnnvl(foo.bar IN ('X', 'Y'));
ORA-13207: incorrect use of the [LNNVL] operator
如果您的表非常大并且您想避免全表掃描,您甚至可以將基于函式的索引定義為
create index idx on foo(nvl(bar,' '));
這將防止在全表掃描,但遺憾的是該指數不能用像往常一樣-你檢查的不公平 <>。
所以結果是一個完整的索引掃描,即你遍歷整個索引并過濾不匹配的鍵,只為正確的鍵訪問表。
如果表很大而結果集很小,這可能很有意義。
執行計劃
--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 250 | 489K| 269 (1)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED| FOO | 250 | 489K| 269 (1)| 00:00:01 |
|* 2 | INDEX FULL SCAN | IDX | 250 | | 185 (2)| 00:00:01 |
--------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(NVL("BAR",' ')<>'X' AND NVL("BAR",' ')<>'Y')
順便提一句
你不能使用索引謂詞lnnvl(bar = 'X')導致明顯的全表掃描與謂詞filter(LNNVL("BAR"='X'))
無論如何,您可以將謂詞重新制定為
WHERE
case when lnnvl(bar = 'X') then 1 end = 1
并定義FBI索引
create index idx2 on foo( case when lnnvl(bar = 'X') then 1 end );
這導致了一個很好的 index range scan
你甚至可以使用and例如
where case when lnnvl(bar = 'X') and lnnvl(bar = 'Y') then 1 end = 1
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/333131.html
上一篇:查詢以考慮具有優先級的分組的型別
