I am trying to calculate a field and I want it to behave differently depending on if one of the columns happens to be null. I am using MySQL
CASE
WHEN reply.replies <> NULL THEN
24/((UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(qcr.LAST_MOD_TIME)+3600)/3600)*(ces.EXPERT_SCORE+2.5*scs.SIMILARITY)*(EXP(-reply.replies))
ELSE 1
END as ANSWER_SCORE
Is this the right syntax?
You need to have when reply.replies IS NOT NULL
NULL is a special case in SQL and cannot be compared with = or <> operators. IS NULL and IS NOT NULL are used instead.
case when reply.replies IS NOT NULL ...
You can't compare NULL with the regular (arithmetic) comparison operators. Any arithmetic comparison to NULL will return NULL, even NULL = NULL or NULL <> NULL will yield NULL.
Use IS or IS NOT instead.
You don't need a case statement for this.
Use the IFNULL function
IFNULL(24/((UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(qcr.LAST_MOD_TIME)+3600)/3600)
*(ces.EXPERT_SCORE+2.5*scs.SIMILARITY)*(EXP(-reply.replies)), 1) as ANSWER_SCORE
If reply.replies is null, the expression is shortcut to NULL
IFNULL then takes the 2nd parameter (1) and gives that as a result when it happens.
For other cases where you do need to compare to NULL, this will help you to work with MySQL.
You can make a CASE Statement Checking Null
SELECT MAX(id+1),
IF(MAX(id+1) IS NULL, 1, MAX(id+1))
AS id
FROM `table_name`;
it would be best if you used is not null in SQL syntax, the '<>' is means the column has value to compare with other sentences.
Related
So I have a SQL statement that was not returning data like it should (MSSQL Server), in part of the query I had this
and t.Invc_Sts_Cd <> 2
turns out if I changed that to
and (t.Invc_Sts_Cd <> 2 OR t.Invc_Sts_Cd IS NULL)
then it returned the data I expected, I would have thought those 2 things would be equivalent but obviously not in TSQL.
Here is the full Statement
SELECT t.tm_sht_id,0
FROM tm_sht t
INNER JOIN cand c ON c.cand_id = t.cand_id
LEFT JOIN SOW_Resource sr on c.Req_Id = sr.Req_Id and (sr.Invoice_Timesheets=1 OR sr.Invoice_Timesheets is NULL)
WHERE t.tm_sht_sts_cd = 3
AND t.apvd_dt >= #Last_Run_Time
and c.clnt_org_id = #Org_Id
and (t.Suspend_Fg <> 1)
and (t.Invc_Sts_Cd <> 2 OR t.Invc_Sts_Cd IS NULL)
My question is why do those return different data sets?
t.Invc_Sts_Cd <> 2 and (t.Invc_Sts_Cd <> 2 OR t.Invc_Sts_Cd IS NULL) are not equivalent, but they are similar.
The key thing you need to understand here is how NULL values work. Nothing is equal to or not equal to NULL, including NULL itself; NULL = NULL isn't TRUE (though is isn't FALSE either, but I come to that shortly). The only way to evaluate against a NULL is using IS NULL and IS NOT NULL.
When doing a comparison against NULL, if you don't use IS (NOT) NULL then the result will be UNKNOWN. For a expression like WHERE Column = 1 then it isn't a problem when Column has the value NULL, as it isn't 1. For other expressions, it does.
For WHERE Column <> 2, when Column has the value NULL it gives result the UNKNOWN, which importantly is not TRUE. Thus the row does not meet to criteria.
The same is true for an expression like WHERE NOT(Column = 1). If Column has the value NULL, then Column = 1 = UNKNOWN and NOT(UNKNOWN) is still UNKNOWN.
Therefore, if you have NULL values, and are performiong comparisons which rely on them, you must include IS NULL and/or IS NOT NULL logic.
Remember, NULL means you don't know what the value is. This is subtly different than not having a value at all. When you don't know what the value is, it's still possible the value might be 2, and therefore NULL <> 2 could still possibly be false... but, again, the result is you don't know.
Therefore, if t.Invc_Sts_Cd is NULL, then t.Invc_Sts_Cd <> 2 must evaluate as... NULL, because we don't know what the result is. And NULL is falsy when you force it into a true/false boolean situation.
This is not about T-SQL, but SQL in general. NULL is the unknown value. If you compare it with some value, the result is hence unknown (i.e. it could or could not match the value).
So both
and t.Invc_Sts_Cd <> 2
and
and t.Invc_Sts_Cd = 2
exclude NULLs from the result, because for a NULL in Invc_Sts_Cd neither expression results in TRUE.
The crux here is that the logical comparison:
t.Invc_Sts_Cd <> 2
is actually false when the Invc_Sts_Cd value is NULL. The reason for this is that comparing NULL to any other value yields the value NULL, which will evaluate to false when it appears inside a WHERE clause.
The second version of your logic is correct:
and (t.Invc_Sts_Cd <> 2 OR t.Invc_Sts_Cd IS NULL)
This will be true when either Invc_Sts_Cd is not equal to 2, or this value happens to be NULL.
I have table, in which a column has empty fields.when i try to run simple query like below it is not
returning the data.
select * from table1 where "colunm1" = ''
But below two queries returns data
1,
select * from table1
where coalesce("colunm1", '') = ''
2,
select * from table1
where "colunm1" is null
Can someone tell me the reason?
TIA
You have describe the behavior of a column that is NULL. NULL is not the same as an empty string.
It fails any equality comparison. However, you can use is null or (less preferentially) coalesce().
The only database that treats an empty string like a NULL value, is Oracle.
Logically, for a DBMS, that would be wrong.
Relational DBMSs are all about :
set theory
Boolean algebra
A NULL value is a value that we don't know. A string literal of '' is a string whose value we know. It is a string with no characters, with a length of 0. We don't know of a NULL as a string how long it is, how many and, if any, which, characters it contains.
So it is only logical that:
the comparison '' = '' will evaluate to TRUE
the comparison NULL = NULL will evaluate to FALSE , as any comparison with a NULL value will evaluate to FALSE.
And functions like COALESCE() or NVL(), IFNULL(), ISNULL() will return the first parameter if it does not contain a NULL value. That is consistent.
Except in Oracle
I am currently learning SQL utilizing Codecademy and am curious if there is a difference between using "IS" or "=".
In the current lesson, I wrote this code:
SELECT *
FROM nomnom
WHERE neighborhood IS 'Midtown'
OR neighborhood IS 'Downtown'
OR neighborhood IS 'Chinatown';
Which ran perfectly fine. I always like to look at the answer after to see if there was something I did wrong or could improve on. The answer had this code:
SELECT *
FROM nomnom
WHERE neighborhood = 'Midtown'
OR neighborhood = 'Downtown'
OR neighborhood = 'Chinatown';
Do IS and = function the same?
All that you want to know you can find it here:
The IS and IS NOT operators work like = and != except when one or both
of the operands are NULL. In this case, if both operands are NULL,
then the IS operator evaluates to 1 (true) and the IS NOT operator
evaluates to 0 (false). If one operand is NULL and the other is not,
then the IS operator evaluates to 0 (false) and the IS NOT operator is
1 (true). It is not possible for an IS or IS NOT expression to
evaluate to NULL. Operators IS and IS NOT have the same precedence as
=.
taken from: SQL As Understood By SQLite.
The important part is: ...except when one or both of the operands are NULL... because when using = or != (<>) and 1 (or both) of the operands is NULL then the result is also NULL and this is the difference to IS and IS NOT.
They work the same but "IS" is a keyword in MySQL and is generally used while comparing NULL values. While comparing NULL values "=" does not work.
SELECT * FROM nomnom WHERE neighborhood IS NULL
The above statement would run perfectly fine but
SELECT * FROM nomnom WHERE neighborhood = NULL
would result in an error.
They are the same for these cases, but further down the line you will discover one nifty little value called NULL.
NULL is a pain because... it doesn't exist.
0 = NULL returns FALSE;
Date <> [Column] will not return lines with NULL, only those with a value that is different.
Hell, even NULL = NULL returns false. And NULL <> NULL also returns false. That is why "IS" exists. Because NULL IS NULL will return true.
So as a general rule, use = for values.
Keep "IS" for null.
[Column] IS NULL
or
[Column] IS NOT NULL
And remember to always check if your column is nullable that you need to plan for null values in your WHERE or ON clauses.
I've a scenrio which process many data in Oracle database. In some cases, the variable Sec_email will contain many values and in some cases Sec_email will contain null or ' '.
so can please any one tell me how to write a query for this?
I tried with
(C.SECONDARY_EMAIL IN ('?,?') OR '' = '' )
where C is the Client table.
When I use this i get the count as 0.
You can perform a not null check before the IN comparison like
Sec_email is not null and C.SECONDARY_EMAIL IN (...
One obvious problem is that Oracle (by default) treats empty strings as NULL. So: '' = '' is the same as NULL = NULL, which is never true.
Arrgh.
In any case, you are probably constructing the query, so use is null instead:
(C.SECONDARY_EMAIL IN ('?,?') OR '' IS NULL
I think the real problem, though, is the first comparison. The IN list has one element with a constant, not two (but perhaps that is your intention). If you want to put a variable number of values for comparison, one method uses regular expressions. For instance:
C.SECONDARY_EMAIL REGEXP_LIKE '^val1|val2|val3$' or '' IS NULL
If you would like to get a list of values when some of them is null you should use:
("some other conditions" OR C.SECONDARY_EMAIL IS NULL)
The question is if it is not null and not ' ' value what you are expecting, if it should be some king of
pattern you should use regular expression:
regexp_like(C.SECONDARY_EMAIL, '^(.+?[,]+?)+$')
Also, if you have a few conditions in where clause use should use brackets to group you conditions null check and another one.
All conditions i this case will be divided by OR.
(C.SECONDARY_EMAIL IS NULL OR regexp_like(C.SECONDARY_EMAIL, '^(.+?[,]+?)+$'))
or
(C.SECONDARY_EMAIL IS NULL OR regexp_like(C.SECONDARY_EMAIL, '^(.+?[,]+?)+$')
OR C.SECONDARY_EMAIL = ' ')
Given:
The following Select statement:
select case NULL
when NULL then 0
else 1
end
Problem:
I'm expecting this to return 0 but instead it returns 1. What gives?
Generally speaking, NULL is not something you should attempt to compare for equality, which is what a case statement does. You can use "Is NULL" to test for it. There is no expectation that NULL != NULL or that NULL = NULL. It's an indeterminate, undefined value, not a hard constant.
-- To encompass questions in the comments --
If you need to retrieve a value when you may encounter a NULL column, try this instead:
Case
When SomeColumn IS NULL
Then 0
Else 1
End
I believe that should work. As far as your original post is concerned:
Select Case NULL
When NULL then 0 // Checks for NULL = NULL
else 1 // NULL = NULL is not true (technically, undefined), else happens
end
The trouble is that your Case select automatically attempts to use equality operations. That simply doesn't work with NULL.
I was going to add this as a comment to Aaron's answer, but it was getting too long, so I'll add it as another (part of the) answer.
The CASE statement actually has two distinct modes, simple and searched.
From BOL:
The CASE expression has two formats:
The simple CASE expression compares an expression to a set of simple expressions to determine the result.
The searched CASE expression evaluates a set of Boolean expressions to determine the result.
When the simple CASE (your example) does what it describes as comparison it does an equality comparison - i.e. =
This is clarified in the later documentation:
The simple CASE expression operates by comparing the first expression
to the expression in each WHEN clause for equivalency. If these
expressions are equivalent, the expression in the THEN clause will be
returned.
Allows only an equality check.
Because anything = NULL is always false in ANSI SQL (and if you didn't know this, you need to read up on NULLs in SQL more generally, particularly also with the behavior in the other searched comparison - WHERE x IN (a, b, c)), you cannot use NULL in a simple case and have it ever be compared to a value, with a NULL either in the initial expression or in the list of expressions to be compared against.
If you want to check for NULL, you will have to use an IF/ELSE construct or the searched CASE with a full expression.
I agree that it's kind of unfortunate there is no version which supports an IS comparison to make it easier to write:
select case colname
when IS NULL then 0
else 1
end
Which would make writing certain long CASE statements easier:
select case colname
when IS NULL then ''
when 1 then 'a'
when 2 then 'b'
when 3 then 'c'
when 4 then 'd'
else 'z'
end
But that's just wishful thinking...
An option is to use ISNULL or COALESCE:
select case COALESCE(colname, 999999) -- 999999 is some value never used
when 999999 then ''
when 1 then 'a'
when 2 then 'b'
when 3 then 'c'
when 4 then 'd'
else 'z'
end
But it isn't always a great option.
In addition to the other answers, you need to change the syntax for CASE slightly to do this:
SELECT CASE
WHEN NULL IS NULL THEN 0
ELSE 1
END;
Using the value in your syntax implicitly uses an equals comparison. NULL is unknown, and so is NULL = NULL, so with your current code you will always get zero 1 (geez I did it too).
To get the behavior you want, you can use SET ANSI_NULLS ON; however note that this can change other code in ways you may not be able to predict, and the setting is deprecated - so it will stop working at all in a future version of SQL Server (see this SQL Server 2008 doc).
You need to use the IS NULL operator. Standard comparison operators do not work with NULL.
Check out these MSDN articles about Null that may be useful:
IS [NOT] NULL (Transact-SQL)
Null Values