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

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.

Related

SQL Server query to return 1 if value exist in a column else return 0

I am trying to query the database for checking if a specific column has a value or not. If there is a value in that column, the query should return 1, else it should return 0.
But my query is returning the total count of the columns for (ex:10).
Note: query is done in Dell Boomi integration platform, SQL Server.
select count (*)
from ApplicationRequest
where EmpID = '993685' and ApplID = '1';
Do you just want case?
select (case when count(*) > 0 then 1 else 0 end)
from ApplicationRequest
where EmpID = 993685 and ApplID = 1;
I removed the single quotes around the comparisons. If they are really numbers then single quotes are not appropriate. If they are indeed strings, then use the single quotes.
If this is what you want, a more efficient method would use exists:
select (case when exists (select 1
from ApplicationRequest
where EmpID = 993685 and ApplID = 1
)
then 1 else 0
end)
The aggregation query needs to find all matching rows. This version can stop at the first one.

Equality check for two boolean expressions (TSQL)

I have two tables and I want to join two tables based on the sign of the related columns
I'm joining on the condition a<0 = b<0 but the equality sign gives me a syntax error. I don't want to do (a<0 AND b<0) OR (Not a<0 AND Not b<0) because it doesn't look clean
You know what the answer is:
where (a < 0 and b < 0) or (a >= 0 and b >= 0)
SQL Server doesn't treat boolean values as bona fide values, so you cannot treat them as regular values in other types of expressions.
You can express this using bitwise or ('^') if you really want:
where (case when a < 0 and b < 0 then 1 else 0 end) ^ (case when a >= 0 and b >= 0 then 1 else 0 end) = 1
However, I find that rather inscrutable.
As Arvo suggested, you can use Sign(). Assuming that a and b are integer types:
where Sign( Sign( a ) + 1 ) = Sign( Sign( b ) + 1 )
Explanation: The inner Sign() calls convert the input values to -1, 0 or 1. Adding 1 shifts those values to 0, 1 or 2. The outer Sign() calls collapse that back to 0 or 1 representing negative and non-negative inputs.
This kind of code is occassionally useful, but should be accompanied by a comment explaining the intent. If the technique is truly impenetrable then it should be explained in the comment or a citation provided.

unusual sql server query result

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.

Can a CASE expression have 2 resultant values

I have to write a case expression in SQL which goes like this,
case condition
if (T_CD = 'Y')
Case C_CD = 'H3'
set R_ID = 3 and RS_ID = 25
CASE A_FLG = 'N' and Mod = 'D'
set R_ID = 3 and RS_ID = 31
Both R_ID and RS_ID populate columns in a different table and have to be derived as per condition above.
My question is - Since I want 2 separate fields out of my case expression, will a single Case give out 2 resultant field values for me. Or Do I have to write 2 different case expressions for it.
If your dbms supports row types, maybe this works for you:
select case when a = 1 then (1,2) else (3,4) end from testtable;
The SQL Validator says:
The following feature outside Core SQL-2003 is used:
T051, "Row types"

Issue with null value using select statement

I am trying to use this select statement but my issue is for this ID that i am trying to use in my select statement has null value. Even though ID 542 has null value but i know for fact in the future is going to have a 'COMPLETE' value in it. The 3 possible values for the FLAG field are COMPLETE, NOT COMPLETE AND NULL. What i want to achieve with this select statement is to see all records where FLAG is not 'COMPLETE'. If i run my query now, it will not return anything but if i remove FLAG <>'COMPLETE' then it will return the record ID 542 but the flag value is null.
Here is my code
SELECT ID, DT, STAT FROM myTable WHERE ID = 542 and FLAG <> 'COMPLETE'
Convert the NULL to text:
SELECT ID, DT, STAT
FROM myTable
WHERE ID = 542 and ISNULL(FLAG,'NULL') <> 'COMPLETE'
SELECT ID, DT, STAT
FROM myTable
WHERE ID = 542 and ISNULL(FLAG, 'NOT COMPLETE') <> 'COMPLETE'
Since the FLAG is null it cannot be compared against 'COMPLETE' and you're missing the entry...
or:
SELECT ID, DT, STAT
FROM myTable
WHERE ID = 542 AND (FLAG <> 'COMPLETE' OR FLAG IS NULL)
Welcome to SQL's three valued logic! The well-known brothers true and false have a secret stepsister called unknown. And the result of a comparison with null is always unknown.
A quick fix is to add an explicit is null check:
where Flag is null or Flag <> 'COMPLETE'
Note that not unknown is still unknown, so this won't work:
where not Flag = 'COMPLETE' -- Won't work
In fact, not even null is equal to null. But null isn't not equal to null either!
For more fun, have a look at Wikipedia. It has a whole page dedicated to three valued logic in SQL.