unusual sql server query result - sql

Let's say I have a table called nameAge:
ID Name Age
1 X 12
2 Y 12
3 null null
4 Z 12
and when I run a query like:
select * from nameAge where Age <> 12
it returns me an empty result set while I have row with id 3 where age is different than null?
Using Sql Server 2008 R2.
Any ideas?
Edit: Possibility to be duplicate with suggested answer may be at one point but does not cover at all and it shows how to use null values when compared with null but what I wanted to ask was about the result set which includes null values

This is the intended behavior. You cannot compare NULL values using = or <>. You have to use IS NULL or IS NOT NULL.
If you want NULL values only use IS NULL:
select * from nameAge where age IS NULL
If you want NULL values with age <> 12 values, use:
select * from nameAge where age <> 12 OR age IS NULL

The expression
WHERE NULL <> 12
does not return TRUE or FALSE, but actually returns UNKNOWN. This means that the third record in your table will not be returned by your query.
As #ughai mentioned, you should use IS NULL instead to query that record:
SELECT * FROM nameAge WHERE age IS NULL
Have a look at the Microsoft SQL Server documentation for more information.

When you are dealing with NULLs you should be always careful because of 3 valued logic used in Sql Server(when a predicate can be evaluated to TRUE, FALSE or UNKNOWN). Now here is a classic select statement where many newcomers make a mistake, suggesting that the statement would return all rows where Age <> 12 including NULLs.
But if you know the easy fact that comparing NULL to any value, even to NULL itself will evaluate to UNKNOWN it is getting more clear what is going on. WHERE clause will return ONLY those rows where predicate is evaluated to TRUE. Rows where predicate evaluates to FALSE or UNKNOWN will be filtered out from resultset.
Now let's see what is going on behind the scene. You have 4 rows:
ID Name Age
1 X 12
2 Y 12
3 null null
4 Z 12
and the predicate is:
where Age <> 12
When you evaluate this predicate for each row you get:
ID Name Age Evaluation result
1 X 12 FALSE --(because 12 <> 12 is FALSE)
2 Y 12 FALSE --(because 12 <> 12 is FALSE)
3 null null UNKNOWN --(because NULL <> 12 is UNKNOWN)
4 Z 12 FALSE --(because 12 <> 12 is FALSE)
Now remember that WHERE clause will return only rows where predicate evaluates to TRUE and it is clear that you will not get any result because no row evaluates to TRUE.

Related

How to return NULL records on a query with a where clause?

I'm using SQL Server 2016 and I have a view setup for novice end users.
To start, let's say there is a table like the following:
id number
=========
1 2
2 4
3 6
4 NULL
5 12
If a user makes a query on the view such as, select * from view1 where number <> 12, the view is setup to return NULL values as -99 using coalesce(number,-99):
Result of 'select * from view1 where number <> 12':
id number
=========
1 2
2 4
3 6
4 -99
Is there anyway to have the view return NULL instead of -99 (or whatever value), without the end user having to include ... or where is null in their query?
I understand NULLs and why it behaves like this, but for convenience I'd rather these end users not have to do this.
No.
The best you can do is fix the result so it decodes -99 as NULL:
SELECT id, CASE WHEN number = -99 THEN NULL ELSE number END AS number
FROM view1
WHERE number != 12
which I believe defeats the purpose of not exposing NULL values to the end user, or approach the data by accounting NULL as a valid data, using OR number IS NULL in that matter.
Try this:
select * from view1 where number <> 12 or number is null

How can I make IF without ELSE on SQL WHERE condition?

I`m trying to make a querie that selects users and if user type equals 1 I need to select those with age. My table:
id (int 11) | type (int 11) | email (varchar 25) | age (int 11)
My querie:
SELECT * FROM users WHERE IF(type = 1, age <> 0)
The problem is that I need to have an ELSE condition, but I dont need one in this case. How can I make an IF inside WHERE without else condition?
Thanks
You can do it with CASE:
SELECT * FROM users
WHERE age = CASE WHEN type <> 1 THEN age ELSE 0 END
Q: How do I make IF without ELSE on SQL WHERE condition ?
A: It's not possible; there is always an ELSE. MySQL IF() function has three arguments. It doesn't matter where the IF() function is used, whether it's part of an expression in a WHERE clause, or an expression in the SELECT list.
As an alternative to the MySQL IF() function, we can use a more portable, more ANSI-standard compliant CASE expression. But that doesn't get away from the crux of the question, about avoiding an ELSE. There is always an ELSE with the CASE expression as well. If we omit the ELSE clause, it's the same as if we had specified ELSE NULL.
As an aside (unrelated to the question that was asked), I don't think we should be storing age as an attribute; typically age is the difference between the current date and a date in the past (date of birth, registration date, etc.)
I'm thinking we don't need an IF function in the WHERE clause. (That's specific to MySQL, so this answer assumes that the target DBMS is MySQL, and not some other RDBMS).
We can use a combination of conditions, combined with NOT, AND, OR and parens so specify an order of operations.
Sample data and example output goes a long way to explaining the spec.
id type age email
-- ---- ---- ----------
1 0 0 1#one
2 1 0 2#two
3 0 1 3#three
4 1 1 4#four
5 0 NULL 5#five
6 1 NULL 6#six
7 NULL NULL 7#seven
8 NULL 0 8#eight
9 NULL 1 9#nine
Which of these rows should be returned, and which rows should be excluded?
Here is an example query (MySQL specific syntax) that returns all rows except row id=2 (type=1, age=0)
SELECT u.id
, u.type
, u.age
, u.email
FROM user u
WHERE NOT ( u.type <=> 1 )
OR NOT ( u.age <=> 0 )
If there's a requirement to incorporate IF functions, we can do that, and return an equivalent result:
SELECT u.id
, u.type
, u.age
, u.email
FROM user u
WHERE NOT ( IF( u.type <=> 1 ,1,0) )
OR NOT ( IF( u.age <=> 0 ,1,0) )
^^^ ^^^^^
In the WHERE clause, an expression will be evaluated as a boolean value. A numeric value of 0 is FALSE, a non-zero value is TRUE, and NULL value is (as always) just NULL.
For a row to be returned, we need the expression in the WHERE clause to evaluate to a non-zero value (to evaluate to TRUE).
The third argument of the IF() function is the "else" value; for that value, we can return TRUE, FALSE or NULL. To exclude rows that do not satisfy the type=1 condition, we return either zero or NULL:
WHERE IF(type = 1, age <> 0 ,0 )
^^
or equivalently:
WHERE IF(type = 1, age <> 0 ,NULL )
^^^^^
If we want rows that don't satisfy type=1 condition to be returned, we can return any non-zero value:
WHERE IF(type = 1, age <> 0 ,42 )
^^^
RECAP:
Addressing the question that was asked:
Q: How do I make IF without ELSE on SQL WHERE condition ?
A: There is always an ELSE value with the MySQL IF() function; in the context of the WHERE clause, the value will be evaluated as a boolean: TRUE, FALSE or NULL.
I think you want:
SELECT *
FROM users
WHERE type <> 1 OR age <> 0;
I was in a similar situation and ended up with the following solution:
SELECT * FROM users WHERE IF(type = 1, age <> 0, 1=0)
The else part here is 1 = 0 which is never true, so you don't select anything in that case.

NULL behavior with Comoperator like ALL in Oracle SQL

SELECT * FROM hr.NullValueCheck
ID Name
1 abc
2 abc
3 bcd
4 cde
https://oracle-base.com/articles/misc/all-any-some-comparison-conditions-in-sql
Query 1 :
SELECT *
FROM hr.NullValueCheck
where id > All (SELECT NULL FROM DUAL )
Nothing is coming.
But for below quesry. All records are coming while subquesry is returning is NULL same as like above query (SELECT NULL FROM DUAL )
Query 2:
SELECT *
FROM hr.NullValueCheck
where id > All (SELECT id from hr.NullValueCheck where id = 5)
Please explain me why Query 1 is returning No Records but Query 2 is returning all records.
As per my knowledge Query 1 should also return all records.
NULL is different from an empty set.
The first example is saying: "select all rows where the id is greater than all values of NULL". Or more simply, "where id is greater than 'NULL'`.
In SQL, 'NULL' generally has the semantics of "not known". If you don't know the value, then you don't know if a given id is larger. Hence, no rows are returned.
In the second example, instead has an empty set for comparison. An empty set is not NULL. Obviously, any number is greater than all numbers in an empty set. Hence, all rows are returned.

Sql: have a column return 1 or 0 denoting if an id exists in a table for a predetermined groupID

I wrote the following SQL to create a column that I can use to populate check boxes in a Grid to manage user permissions.
SELECT access_b2b.access_id,
access_b2b.description,
'active'= CASE
WHEN access_group.group_id IS NOT NULL THEN 1
ELSE 0
END
FROM access_b2b
LEFT JOIN access_group
ON access_group.access_id = access_b2b.access_id
WHERE ( access_group.group_id = 10
OR access_group.group_id IS NULL )
However, it does not select all of the entries from access_b2b. The issues is with the last line:
where (access_group.group_id=10 or access_group.group_id is null)
Without it, i get duplicate entries returned with different active values. Also, I realized that this is not the proper condition, because an entry in access_group might exist for a different access_group.group_id, meaning that not all the remaining entries will be pulled in with the access_group.group_id is null.
I am trying to write my condition so that if does something along the lines of:
This is the format I was trying to follow:
Where For Each unique access_id in access_group
select the one where group_id=10
if no group_id=10
select any other one
end
end
Ultimately, the goal is to have a column returned with 1 or 0 denoting if the access_id exists for a predetermined group id.
Please note that throughout this explanation I used group_id=10 for simplification, it will be later replaced with a SqlParameter.
Any help is appreciated, thank you so much!
SAMPLE DATA (only useful columns shown to simplify data)
access_group
access_id group_id
27 1
27 11
28 1
28 11
33 1
33 3
33 11
43 11
44 1
44 10
44 11
...
access_b2b
access_id description
1 Add
2 Edit
3 Delete
4 List
5 Payments
6 Open Files
7 Order
8 Mod
...
Change the query to and it should work:
SELECT access_b2b.access_id,
access_b2b.description,
'active'= CASE
WHEN access_group.group_id IS NOT NULL THEN 1
ELSE 0
END
FROM access_b2b
LEFT JOIN access_group
ON access_group.access_id = access_b2b.access_id
AND ( access_group.group_id = 10
OR access_group.group_id IS NULL )
If you don't want the records to be filtered by the WHERE clause, move the condition in the JOIN.
The JOIN will keep the lines and populate them with NULL if the condition is not met, while the WHERE clause will filter the result set.

SQL query to add values of two columns containing null values?

Given table:
ID ONE TWO
X1 15 15
X2 10 -
X3 - 20
This query:
SELECT (ONE + TWO) FROM (TABLE)
Just returns the sum of X1's values but not the others since at least one column has a null value. How can I still add them even if there is a null? i.e. consider the null as a 0 maybe?
SELECT (COALESCE(ONE, 0) + COALESCE(TWO, 0)) FROM (TABLE)
COALESCE will return the first non-null value found in the parameters from left to right. So, when the first field is null, it will take the 0.
That way, X2 will result in 10 + 0 = 10
there is already a good answer, but I think it is worth mention to the antonpug (in case he doesn't know) that the reason why this is happening is that NULL is not a value that can be compared or summed.
NULL isn't 0 or '' (empty string), so every operation involving NULL will result NULL (10 + NULL = NULL), even (NULL=NULL) will evaluate to FALSE