We'd like to write this query:
select * from table
where col1 != 'blah' and col2 = 'something'
We want the query to include rows where col1 is null (and col2 = 'something'). Currently the query won't do this for the rows where col1 is null. Is the below query the best and fastest way?
select * from table
where (col1 != 'blah' or col1 is null) and col2 = 'something'
Alternatively, we could if needed update all the col1 null values to empty strings. Would this be a better approach? Then our first query would work.
Update: Re: using NVL: I've read on another post that this is not considered a great option from a performance perspective.
In Oracle, there is no difference between an empty string and NULL.
That is blatant disregard for the SQL standard, but there you go ...
In addition to that, you cannot compare against NULL (or not NULL) with the "normal" operators: "col1 = null" will not work, "col1 = '' " will not work, "col1 != null" will not work, you have to use "is null".
So, no, you cannot make this work any other way then "col 1 is null" or some variation on that (such as using nvl).
I think that the solution that you posted is one of best options.
Regarding to performance, in my opinion it is not a big difference in this case, if the clause already have a != comparison usually the optimizer won't use an index in that column, because the selectivity is not enough, so the more discriminating filter will be the other side of the "and" condition.
If you ask me, I won't use an empty string as a null, but may be is just a personal preference.
While not the most readable - Oracle has an LNNVL Function that is essentially the not() function, but inverts the behavior for nulls. Meaning that comparing anything with null inside of lnnvl will return true (I don't know what performance implications this may have).
To do what you want in a single statement:
select * from table where lnnvl(col1 = 'blah') and col2 = 'something'
Note that this will only work for comparing a nullable value against a value you can be assured is non-nullable. Otherwise you'll need to do as Thilo suggests - use an operator similar to
lnnvl(nvl(col1, -1) = nvl(col2, -1))
It depends on your data, but most optimizers are going to look at col2 before col1, since = is an easier index than !=.
Otherwise, there are various ways you can speed this query up. It's probably best to do (col1 != 'blah' or col1 is null), but some database allow you to index a function. So you can index coalesce(col1, 0) and get good performance.
Really it depends on you data and your table.
In oracle use the nvl function
select * from table where nvl(col1,'notblah') <> 'blah'
If you want to speed up this sort of query, and you're on Oracle 10g or later, use a function-based index to turn those NULLs into values:
CREATE INDEX query_specific_index ON table (col2, NVL(col1,'***NULL***'));
select * from table
where NVL(col1,'***NULL***') != 'blah' and col2 = 'something';
The database will quite likely use the index in this scenario (of course, subject to the decision of the CBO, affected by row counts and the accuracy of the statistics). The query MUST use the exact expression given in the index - in this case, "NVL(col1,'***NULL***')"
Of course, pick a value for '***NULL***' that will not conflict with any data in col1!
What about this option. I think it may work if your value is never null.
where not (value = column)
which would result in following truth table for evaluation for the where clause
col1
| 'bla' | null |
-----------------
| 'bla' | F | T |
value -------------------------
| null | T | *T |
*this is the only one that's "wrong" but that's ok since our value is never null
Update
Ok, I just tried out my idea and it failed. I'll leave the answer here to save time of others trying the same thing. Here are my results:
select 'x', 'x' from dual where not ('x' = 'x');
0 rows
select 'x', 'y' from dual where not ('x' = 'y');
1 row
select 'x', 'null' from dual where not ('x' = null);
0 rows
select 'null', 'null' from dual where not (null = null);
0 rows
Update 2
This solution works if your value is never null (matches the truth table above)
where ('blah' != col1 or col1 is null)
tests here:
select 'x', 'x' from dual where ('x' != 'x' or 'x' is null);
0 rows
select 'x', 'y' from dual where ('x' != 'y' or 'y' is null);
1 row
select 'x', 'null' from dual where ('x' != null or null is null);
1 row
select 'null', 'null' from dual where (null != null or null is null);
1 row
For Oracle
select * from table where nvl(col1, 'value') != 'blah' and col2 = 'something'
For SqlServer
select * from table where IsNull(col1, '') <> 'blah' and col2 = 'something'
I think that your increase would be minimal in changing NULL values to "" strings. However if 'blah' is not null, then it should include NULL values.
EDIT: I guess I'm surprised why I got voted down here. If 'blah' if not null or an empty string, then it should never matter as you are already checking if COL1 is not equal to 'blah' which is NOT a NULL or an empty string.
Related
I have a prepared SQLite statement...
SELECT * FROM a WHERE col1 = $someValue
But when someValue is null the query returns no rows, so I wrote this...
SELECT *
FROM a
WHERE (
col1 = $someValue OR
(
$someValue IS NULL AND
col1 IS NULL
)
)
This query works perfectly regardless of someValue being null or not, but it's very verbose. Is there a simpler or more succinct way of achieving the same?
From Operators, and Parse-Affecting Attributes:
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.
You can use the operator IS to compare non-null values as well:
SELECT * FROM a WHERE col1 IS $someValue;
If you would be using postgres there was is distinct from and I guess they have it because many feel with you:
SELECT * FROM a WHERE col1 is not distinct from $someValue
With sqlite it should be possible to write:
SELECT * FROM a WHERE col1 is $someValue OR col1 = $someValue
That is probably as short as it gets.
Not as elegant as forpas's answer, but another alternative worth mentioning:
SELECT * FROM a WHERE ifnull(col1, 'x') = ifnull($someValue, 'x')
where the second parameter passed to the ifnull function, in this case x, is a value not already in the database and col1 and $someValue are varchar columns.
I am not getting expected result when mentioned Not Null check with one Numeric value on same column. It's returning all the values.
Select *
from TableName
where Col1 = value
and (col2 is Not Null or col2 <> 123)
Here, col2 is Numeric column.
Expected Result = Exclude records where Col2 having Null value or 123
Please help me on this issue.
I'm guessing that you are getting all the rows, except the NULL ones. One solution is to replace the or with and. But that logic is actually redundant:
where Col1 = value and col2 <> 123
NULL fails the <> 123 comparison, so you don't need another check.
I get the correct result from below query. As per following requirement, I was using Or in place of And.
Select *
from TableName
where Col1 = value
and (col2 is Not Null and col2 <> 123)
When I used this code
WHEN col1 NOT IN (SELECT col2 FROM table_name) THEN 'something'
it didn't give the expected results knowing that col2 contains a NULL value, Why did this happened ? Does using IN with NULL values messes with data stored in memory or what?
This is not an issue with Oracle. This is how SQL is defined.
When the subquery returns a NULL value with NOT IN, then no rows match at all. For this reason, I strongly recommend always using NOT EXISTS instead:
WHEN NOT EXISTS (SELECT 1 FROM bst WHERE x.n = bst.p)
THEN 'Leaf'
As a corollary, I usually use EXISTS instead of IN, even though it does not have this problem.
Why does this occur? NULL means that the value is unknown, not that the value is "missing" or something else.
So, if all the elements have values, this is easy to calculate:
1 NOT IN (1, 2) --> false
3 NOT IN (1, 2) --> true
However:
1 NOT IN (1, 2, NULL) --> false
3 NOT IN (1, 2, NULL) --> NULL, because NULL could be equal to "3"
Basically, if any value is NULL, then NOT IN returns either "false" or NULL. Both "false" and NULL are treated the same in WHEN and WHERE.
I am currently trying to compare two SQL server database tables. I've found various methods online, some which seem to work, other which don't.
The one I used which worked was:
select * from table1
except
select * from table2
The only issue with this then (as far as I am aware) is, the table says there is a difference between a 'NULL' value and a '0'. Which is correct, there is a difference.
However my question is, is there a way to do the comparison difference check, whilst ignoring certain conditions such as NULL and 0.
You can use
select isnull(column1, 0) as column1 from table1
except
select isnull(column1, 0) as column1 from table2
to consider the values 0 and null as same.
Also, If you wish to consider more values as same like null = 0 = '' (empty string)
You can use case:
select case when (column1 is null or column1 = '') then 0 end as column1 from table1
except
select case when (column1 is null or column1 = '') then 0 end as column1 from table2
How do you write a SELECT statement that only returns rows where the value for a certain column is null?
Do you mean something like:
SELECT COLUMN1, COLUMN2 FROM MY_TABLE WHERE COLUMN1 = 'Value' OR COLUMN1 IS NULL
?
I'm not sure if this answers your question, but using the IS NULL construct, you can test whether any given scalar expression is NULL:
SELECT * FROM customers WHERE first_name IS NULL
On MS SQL Server, the ISNULL() function returns the first argument if it's not NULL, otherwise it returns the second. You can effectively use this to make sure a query always yields a value instead of NULL, e.g.:
SELECT ISNULL(column1, 'No value found') FROM mytable WHERE column2 = 23
Other DBMSes have similar functionality available.
If you want to know whether a column can be null (i.e., is defined to be nullable), without querying for actual data, you should look into information_schema.
Use Is Null
select * from tblName where clmnName is null
You want to know if the column is null
select * from foo where bar is null
If you want to check for some value not equal to something and the column also contains null values you will not get the columns with null in it
does not work:
select * from foo where bar <> 'value'
does work:
select * from foo where bar <> 'value' or bar is null
in Oracle (don't know on other DBMS) some people use this
select * from foo where NVL(bar,'n/a') <> 'value'
if I read the answer from tdammers correctly then in MS SQL Server this is like that
select * from foo where ISNULL(bar,'n/a') <> 'value'
in my opinion it is a bit of a hack and the moment 'value' becomes a variable the statement tends to become buggy if the variable contains 'n/a'.
select Column from Table where Column is null;
select * from tableName where columnName is null
For some reasons IS NULL may not work with some column data type. I was in need to get all the employees that their English full name is missing, I've used:
SELECT emp_id, Full_Name_Ar, Full_Name_En
FROM employees
WHERE Full_Name_En = '' or Full_Name_En is null