Question

I don't understand Teradata's implementation for null inequality comparisons. You can run this SQL right in SQLA:

select 
    null x, current_date y,
    case
        when 
            not 
            --ZEROIFNULL(x) = ZEROIFNULL(y)
            ((x is null and y is null) or x = y)
        then 1 
        else 0 
    end z

You will notice that z returns 0, but I feel that it should return 1. Here's my reasoning:

x is null and y is null This should return false since only x is null.

x = y This should return false since both are not equal.

However, when I put not in front of the entire expression, it returns false. When you say not false, you should get true. The only solution I can think of is to use ZEROIFNULL or one of Teradata's other null-related functions, but that seems more like a hack to get null inequality to work.

How can I get null inequality to work the way it seems like it should?

Update: Thanks for your answer, dnoeth. Nulls are tricky, and your explanation of unknown lead me to this very informative Wiki article.

Now that I understand better, here's my fully modified SQL. What I am trying to do is determine whether or not to move a record to an audit table. I only want to audit a record if 1) its AuditOverride flag = 1 OR at least one of the fields has changed. Throwing an unknown into a condition that contains multiple expressions will result in the entire expression returning unknown. Because putting not in front of unknown also results in unknown, I use a case statement to convert that to 0 (like zeroifnull).

dnoeth, if you see a better way to handle inequality comparisons such as this, I am all for hearing your ideas.

select 
    1 Table1Field1, 1 Table1Field2,
    1 Table2Field1, 1 Table2Field2,
    0 AuditOverride,
    case 
        when 
            AuditOverride = 1 or
            case
                when 
                    (
                        (Table1Field1 is null and Table1Field2 is null) or 
                        Table1Field1 = Table1Field2
                    ) and
                    (
                        (Table2Field1 is null and Table2Field2 is null) or 
                        Table2Field1 = Table2Field2
                    ) and
                    1=1
                then 0 --no differences in values; do not audit
                else 1 --at least 1 change has occurred; move to audit table
            end = 1
        then 1
        else 0 
    end MoveToAuditTable
Was it helpful?

Solution

This is not only a Teradata related question, this is three-way logic every RDBMS should return the same :-)

Based on SQL's Three-Valued Logic and De Morgan's law:

not (A or B) is the same as (not A) AND (not B).

Any comparison with NULL returns UNKNOWN which is not the same as FALSE, NOT UNKNOWN results in UNKNOWN again.

So your condition is NOT FALSE AND NOT UNKNOWN = TRUE AND UNKNOWN = UNKNOWN

You must change it to:

select 
    null x, current_date y,
    case
        when 
            ((x is null and y is null) or x = y)
        then 0
        else 1 
    end z
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top