Обоснование LNNVL

12

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

Например, предположим, что у вас есть таблица Emp со столбцами StartCommission и CurrentCommission, которые могут содержать нули. Следующее возвращает только строки с нулевым значением:

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);

Добавление NOT к этому возвращает только строки без нулей. Мне кажется, что желаемая функциональность для этого случая состояла бы в том, чтобы истинные условия были истинными, ложные условия ложными, и чтобы неизвестные условия оценивались как истинные. Я действительно создал случай низкого использования здесь? Действительно ли более вероятно захотеть превратить неизвестное в истинное, истинное в ложное и ложное в истинное?

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); так что он возвращает тот же результат, что и оператор с использованием OR. Другими словами, если мы используем условие, и мы также хотим включить строки, имеющие значение NULL, нам нужно передать отрицание нашего условия в LNNVL.
Только ты
Еще один простой пример. Только сотрудники, которые фактически получают комиссию менее 20%: SELECT * FROM сотрудников WHERE Commission_pct <.2; Также включить сотрудников, которые вообще не получают комиссию: SELECT * FROM сотрудников WHERE LNNVL (Commission_pct> = .2);
Только ты
@OnlyYou - Вы правы, что для того, чтобы LNNVL работал одинаково, условие должно быть <>. Я оставил это = больше, потому что если бы функция возвращала те же результаты со знаком =, это имело бы больше смысла. По сути, функция выполняет два действия: 1. Нулевое включение, 2. Булево переключение. Первое имеет смысл, позднее кажется, что все путает вещи, требующие противоположности желаемого условия. т.е. = требуется <>, <требуется> = и т. д.
Ли Риффель

Ответы:

6

Это странная функция со странной историей, но так же странна и nvl2 . lnnvlэто в основном is not trueоператор - без сомнения, его можно использовать как « nvl2банку», но когда вам приходится искать функцию каждый раз, когда вы используете ее, чтобы напомнить вам точно, что она делает, вам остается только подумать, лучше ли придерживаться nvl, coalesce, decodeи nullifвместе с caseвыражениями, которые являются более интуитивным

Джек говорит, попробуйте topanswers.xyz
источник
Я не нахожу NVL2 странным, но потом я часто его использую и никогда не использовал LNNVL.
Ли Риффель
@Leigh - я думаю, вы должны использовать его достаточно часто, чтобы он не становился странным :) Я никогда не использовал его, nullifпока не понял, что это может быть очень полезным, чтобы сделать «деление на ноль» = ноль. Вы действительно находите nvl2 (a, c, b) намного лучше, чем decode (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 - я понимаю, и я думаю, что именно это и хотел Керри.
Ли Риффель