Обґрунтування LNNVL


12

LNNVL - вбудована функція oracle, яка повертає TRUE для оцінювання умов FALSE або UNKNOWN та повертає FALSE для умов, що оцінюються на TRUE. Моє запитання: яка користь буде повернути протилежне умові істини, а не просто обробляти значення NULL?

Наприклад, припустимо, що у вас є таблиця Emp зі стовпцями StartCommission та CurrentCommission, яка може містити нулі. Наступні повертає лише рядки, які не мають значення null:

SELECT * FROM Emp WHERE StartCommission = CurrentCommission;

Якщо ви хочете включити рядки, де будь-яка комісія є нульовою, ви можете зробити щось подібне:

SELECT * FROM Emp WHERE StartCommission = CurrentCommission 
OR StartCommission IS NULL OR CurrentCommission IS NULL;

Здавалося б, існує функція для скорочення цього синтаксису, але за допомогою LNNVL повертає всі нерівні записи та всі записи з нулями.

SELECT * FROM Emp WHERE LNNVL(StartCommission = CurrentCommission);

Додавання НЕ до цього повертає лише рядки без нулів. Мені здається, що бажаною функціональністю для цього випадку було б зберігати справжні умови істинні, помилкові умови неправдиві та невідомі умови оцінювати як істинні. Чи справді я створив справу з низьким рівнем використання? Чи справді більше шансів хотіти перетворити невідоме на справжнє, справжнє на помилкове, а хибне на справжнє?

create table emp (StartCommission Number(3,2), CurrentCommission Number(3,2));
insert into emp values (null,null);
insert into emp values (null,.1);
insert into emp values (.2,null);
insert into emp values (.3,.4);

Сьогодні я познайомився з LNNVL і намагаюся також з’ясувати чи зрозуміти цю частину, «яка б користь повернення протилежної істини». Однак у операторі, який ви використовуєте для прикладу LNNVL, слід використовувати нерівний оператор: SELECT * FROM Emp WHERE LNNVL (StartCommission <> CurrentCommission); так що він повертає той самий результат, що й оператор, використовуючи АБО. Іншими словами, якщо ми використовуємо умову, а також хочемо включити рядки, що мають значення NULL, нам потрібно передати негатив нашої умови LNNVL.
Тільки ти

Ще один простий приклад. Тільки працівники, які насправді отримують комісію менше 20%: ВИБІРАТИ * ВІД співробітників, КОМИ комісія_pct <.2; Щоб також включити співробітників, які взагалі не отримують комісії: ВИБІРІТЬСЯ * З працівників, де LNNVL (Commission_pct> = .2);
Тільки ти

@OnlyYou - Ви праві, що для того, щоб LNNVL працював однаково, умовою повинно бути <>. Я залишив це = більше, тому що якщо функція поверне ті самі результати зі знаком =, це матиме більше сенсу. По суті, функція виконує дві дії: 1. Нульове включення, 2. Булеве перемикання. Перший має сенс, пізніше просто здається, що плутає речі, що вимагають протилежного бажаному умові. тобто = вимагає <>, <вимагає = = і т. д.
Лі Риффер

Відповіді:


6

Це дивна функція із дивною історією, але тоді так само nvl2 дивно. lnnvlв основному це is not trueоператор - без сумніву, його можна використовувати так, як nvl2можна, але коли вам потрібно шукати функцію кожного разу, коли ви її використовуєте, щоб нагадати вам, що саме вона робить, вам залишається цікаво, чи найкраще дотримуватися nvl, coalesce, decodeі nullifразом з caseвиразами, які є більш інтуїтивним


Я не вважаю NVL2 дивним, але тоді я його багато використовую, і ніколи не використовував LNNVL.
Лі Ріффер

@Leigh - я думаю, вам доведеться використовувати його досить часто, щоб він не став дивним :) Я ніколи не використовував, nullifпоки не зрозумів, що це може бути великою допомогою зробити «поділ на нуль» = null. Ви дійсно вважаєте, що nvl2 (a, c, b) набагато краще, ніж декодування (a, null, b, c)?
Джек каже, спробуйте topanswers.xyz

4

Якщо говорити так, я ще не один раз використовував LNNVL за кілька років роботи DBA і PL / SQL-програмістом. Я використовував NVL2 при нагоді (і завжди повинен був шукати, яка сторона справжня, а яка - ні). З цього моменту, здається, краще з точки зору читабельності в кінцевому підсумку використовувати NVL, DECODE, CASE тощо,

Крім того, це працює, якщо припустити, що у вас є хороша робота щодо того, як Oracle обробляє NULL і арифметику, але до цього моменту ви також можете використовувати ваш оригінальний запит для читабельності (і план виконання може спричинити і більш важкий удар):

/* Return all rows where StartCommission is the same
 * as Current Commission, or those rows who have a
 * NULL in either (including both)
 */

SELECT *
  FROM Emp
 WHERE StartCommission = CurrentCommission
    OR StartCommission + CurrentCommission IS NULL

-- NULL + NULL, or NULL + Number is always NULL; hence return either
-- those records that are equal, or have a combined total of NULL
-- (either or both fields will be NULL).

Ви маєте на увазі StartCommission<>CurrentCommission OR StartCommission + CurrentCommission IS NULL?
Джек каже, спробуйте topanswers.xyz

@JackPDouglas - Це має сенс як =.
Лей Ріффер

Цікава варіація. Я згоден з вашими висновками.
Лей Ріффель

@Leigh - Я бачу, альтернатива потрібній вам функції, а не альтернатива lnnvl.
Джек каже, спробуйте topanswers.xyz

@JackPDouglas - Я розумію, і я думаю, що це Керрі мав намір.
Лі Ріффель
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.