Uzasadnienie LNNVL


12

LNNVL jest wbudowaną funkcją wyroczni, która zwraca PRAWDA dla warunków ewaluujących do FAŁSZ lub NIEZNANY, i zwraca FAŁSZ dla warunków ewaluujących do PRAWDA. Moje pytanie brzmi: jaka byłaby korzyść ze zwrócenia przeciwieństwa warunku prawdy, a nie tylko obsługi wartości NULL?

Załóżmy na przykład, że masz tabelę Emp z kolumnami StartCommission i CurrentCommission, która może zawierać wartości null. Poniższe zwraca tylko wiersze bez wartości null:

SELECT * FROM Emp WHERE StartCommission = CurrentCommission;

Jeśli chcesz dołączyć wiersze, w których prowizja jest zerowa, możesz zrobić coś takiego:

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

Wydaje się, że istnieje funkcja skracająca tę składnię, ale użycie LNNVL zwraca wszystkie nierównomierne rekordy i wszystkie rekordy z zerami.

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

Dodanie NOT do tego zwraca tylko wiersze bez wartości null. Wydaje mi się, że pożądaną funkcjonalnością w tym przypadku byłoby utrzymanie prawdziwych warunków prawdziwych, fałszywych warunków fałszywych, a nieznane warunki ocenione jako prawdziwe. Czy naprawdę stworzyłem tutaj przypadek niskiego użycia? Czy naprawdę bardziej prawdopodobne jest, że zechce przekształcić nieznane w prawdziwe, prawdziwe w fałszywe, a fałszywe w prawdziwe?

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

Dzisiaj spotkałem LNNVL i staram się również dowiedzieć lub zrozumieć tę część „jaka byłaby korzyść z odwrotności prawdy”. Jednak instrukcja użyta do zilustrowania LNNVL powinna używać nierównomiernego operatora: SELECT * FROM Emp WHERE LNNVL (StartCommission <> CurrentCommission); tak, że zwraca taki sam wynik jak instrukcja przy użyciu OR. Innymi słowy, jeśli używamy warunku i chcemy również uwzględnić wiersze o wartości NULL, musimy przekazać negację naszego warunku do LNNVL.
Only You

Kolejny prosty przykład. Tylko pracownicy, którzy faktycznie otrzymują prowizję mniejszą niż 20%: WYBIERZ * OD pracowników, GDZIE prowizja_pct <.2; Aby uwzględnić także pracowników, którzy w ogóle nie otrzymują prowizji: WYBIERZ * OD pracowników, GDZIE LNNVL (prowizja>> .2);
Tylko Ty

@ Tylko ty - Masz rację, że aby LNNVL działał tak samo, warunkiem musiałby być <>. Zostawiłem = więcej, ponieważ jeśli funkcja zwróci te same wyniki ze znakiem =, to będzie bardziej sensowne. Zasadniczo funkcja wykonuje dwie akcje 1. Włączenie wartości NULL, 2. Przełączenie boolowskie. Pierwsze ma sens, drugie wydaje się mylić rzeczy wymagające odwrotności pożądanego warunku. tj. = wymaga <>, <wymaga> = itd.
Leigh Riffel

Odpowiedzi:


6

To dziwna funkcja z dziwną historią - ale tak samo jest z NVL2 . lnnvljest w zasadzie is not trueoperatorem - bez wątpienia można go dobrze wykorzystać nvl2, ale gdy trzeba za każdym razem szukać funkcji, aby przypomnieć jej dokładnie, co robi, pozostaje się zastanawiać, czy najlepiej trzymać się tej funkcji nvl, coalesce, decodea nullifwraz z casewyrażeń, które są bardziej intuicyjne


NVL2 nie wydaje mi się dziwny, ale potem często go używam i nigdy nie korzystałem z LNNVL.
Leigh Riffel

@Leigh - Myślę, że musisz go używać wystarczająco często, aby nie stał się dziwny :) Nigdy nie korzystałem, nullifdopóki nie zdałem sobie sprawy, że może być świetną pomocą w dzieleniu przez zero na zero. Czy naprawdę uważasz, że nvl2 (a, c, b) jest znacznie lepszy niż dekodowanie (a, null, b, c)?
Jack mówi, że spróbuj topanswers.xyz

4

Ujmując to w ten sposób, jeszcze raz nie korzystałem z LNNVL przez kilka lat pracy jako programista DBA i PL / SQL. Czasami korzystałem z NVL2 (i zawsze musiałem sprawdzić, która strona była prawdziwa, a która nie). W tym momencie wydaje się lepiej z punktu widzenia czytelności, aby używać NVL, DECODE, CASE itp.,

Alternatywnie działa to, zakładając, że dobrze rozumiesz, w jaki sposób Oracle obsługuje wartości NULL i arytmetykę, ale do tego momentu można równie dobrze użyć oryginalnego zapytania o czytelność (a plan wykonania może również wymagać mocniejszego trafienia):

/* 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).

Czy masz na myśli StartCommission<>CurrentCommission OR StartCommission + CurrentCommission IS NULL?
Jack mówi, że spróbuj topanswers.xyz

@JackPDouglas - Ma sens jako =.
Leigh Riffel

Ciekawa odmiana. Zgadzam się z twoimi wnioskami.
Leigh Riffel

@Leigh - Widzę, alternatywę dla funkcji, którą chcesz, a nie alternatywę dla lnnvl.
Jack mówi, że spróbuj topanswers.xyz

@JackPDouglas - Rozumiem i myślę, że właśnie tego chciał Kerri.
Leigh Riffel
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.