views:

85

answers:

3

Hi. I'm having some difficulty in understanding the following WHERE clause in a T-SQL (SQL Server 2000/2005) query:

update #tempTable
SET
    Total_Avg=isnull(TerminationReason,'terminated'),
    Individual_Subscriptions=null,
    Business_Subscriptions=null,
    Other_subscriptions=null,
    -- snip. 10 more fields set to NULL.
    PMIE_BI=null,
    Digital_Editions_BI=null
where
(
    AbcTerminationDate<=dbo.fnGetPeriodFinalDate(@periodid)
    and (AbcTerminationDate!=19000101 or  AbcTerminationDate is  null)
    and (Total_Avg is not NULL or PrevTotalAvg is not NULL)
)

Specifically, the second clause doesn't make sense to me - it's 2 sub-clauses separated by the OR operator seem contradictory.

The AbcTerminationDate field is declared as INT NULL in a table called Members. I believe a date of 19000101 in the system means NULL or a default value or no value, i.e. that a member is NOT terminated. So the query appears to blank out a whole lot of fields/figures if a member is marked as terminated, which would be when the AbcTerminationDate is NULL or has the default value.

Without knowing any more information, what do you make of it?

+1  A: 

If the "or" arg were outside the () grouping it would negate:

AbcTerminationDate<=dbo.fnGetPeriodFinalDate(@periodid) 

[edit] Basically it's saying to take whatever results are true from that 1st clause, and perform an additional filter to make sure it's not 19000101 or it's null, are most likely exceptional values for the fnGetPeriodFinalDate function to properly evaluate.

James
Thanks.. makes sense. I'm mostly interested in the 2nd clause and what it means, but the results of it could negate the 1st clause, so the 1st clause needs to be considered as well to extract meaning...
Saajid Ismail
+3  A: 

It does look like those are contradictory. Perhaps they meant and !(AbcTerminationDate==19000101 or AbcTerminationDate is null) ?

Curtis
Exactly what I was thinking. Was hoping someone else would have picked this up too..
Saajid Ismail
http://en.wikipedia.org/wiki/De_Morgan%27s_laws is what I was thinking. But they somehow managed to stuff it up, but somehow it still worked due to some weird logic, and only fails in certain edge cases.
Saajid Ismail
+1  A: 

Whatever 19000101 is "supposed" to mean, it is not the same as NULL in the eyes of the database. NULL is NULL. If you try to evaluate any other value to NULL then it can become problematic, because NULL means "unknown". For example, does 1=NULL? Maybe it does, maybe it doesn't. In fact, you can't even say that NULL=NULL, because each NULL is unknown so might or might not be equal to the other. It's safest to explicitly check for NULL conditions.

EDIT: As I point out in my comment, if NULLs are to be included then the first part of the query precludes that. Here is how it should be written if NULLs should be included:

(
    (
        (
            AbcTerminationDate <= dbo.fnGetPeriodFinalDate(@periodid) AND
            AbcTerminationDate != 19000101
        ) OR
        AbcTerminationDate is NULL
    ) AND
    (Total_Avg is not NULL or PrevTotalAvg is not NULL)
)
Tom H.
Agreed, and the above code seems like fairly common practice. Just because AbcTerminationDate doesn't equal "19000101" doesn't mean that it equals NULL...as you said, you have to specifically test for that.
Faisal
I don't dispute what you are saying, and I understand what NULL means from a technical perspective. But that isn't my question. In the system, a date value of 19000101 is 'sementically' equivalent to a NULL value. I'm more interested in the semantic value of the query - what are they trying to achieve?
Saajid Ismail
If it's not the dummy date then include it. If it's NULL, then include it. Again, regardless of the semantics the query still needs to be technically correct if you want the correct results. That's what that line of code is trying to do - make sure that the correct results are returned if the date is NULL. It's not doing it well though, because if it's NULL then the first part of the query will likely fail.
Tom H.
"It's not doing it well though, because if it's NULL then the first part of the query will likely fail". That is my feeling as well. Although this type of WHERE clause is used in a lot of places throughout the system. If is is incorrect, then why hasn't the client complained earlier or more often about it. Perhapds it only fails in certain edge cases...
Saajid Ismail
It would only fail when AbcTerminationDate is NULL. If your application fills that with 19000101 by default then that may not happen. The fact that the column allows NULL means it theoretically *could* happen, so I would always code for it, but maybe it just doesn't.
Tom H.