SQL Case statement returning true although should be false - sql

I have a SQL statement that is something like this
SELECT t1.*
CASE
WHEN t1.COL1 = 0 THEN 0
WHEN
(t1.COL2 = 'val' OR t1.COL3 = 'val' etc) AND ((SELECT COUNT(*) FROM t1 WHERE etc...) > 0)
THEN Run same sub query
WHEN
something else
THEN defaultvalue
END as brokencase
Now, the second WHEN statement above, when run alone, is returning zero. However when it is run here, I am getting a bunch of null values back because that statement is somehow returning true.
So why is the count statement returning zero, but the WHEN statement thinks its true? I have left out a lot of details here for privacy reasons, but this is the general problem.

Usually when I see this, the programmer is missing an ELSE or DEFAULT case in their statements. To find out what scenario you're not capturing, set up a select like this:
SELECT DISTINCT columnTested1, columnTested2, columnTestedX, case statement
FROM blah
Show all the columns being tested, then your case, what you'll see in the result is the combination of columns that are causing your NULL. You need to capture those in your case statement or you'll continue to miss those options
When you test different columns in the different options, you might need multiple else statements to catch them all. Once you've identified the combination of columns causing you a problem, it becomes dead simple to fix the case statement.

If you want to exclude results that have null values you will have to make sure you are checking for that in your WHEN condition. You haven't specified your WHERE clause in your count query so I can't say for sure if this is the problem. It would look something like this:
SELECT COUNT(*) FROM t1 WHERE ExcludeValue IS NOT NULL

Related

SQL Statement with CASE when there are no values

I am trying to use CASE statement for the following, however it is not getting desired results.
What I would like to have is if there are no values based on where condition, then I would like to return 'N' as the result.
SELECT CASE WHEN val IS NULL THEN 'N' else val END
from (select nvl(is_expired,'x')val
FROM test
WHERE product_no = '12DF')
When product_no 12DF doesn't exist in table, I would like to return a value instead of empty or null.
Table structure is specified here
If there are no products '12DF', then you won't get any lines from your subselect.
I'm not quite sure which problem you want to solve.
If you have embedded this in a program, because you can get a result set containing more than one row, that code should be able to handle an empty set as well.
If you expect zero or one lines in your result set, you can use an aggregate function like max.
select nvl(max(is_expired), 'N')
from test
where product_no = '12DF';

SQL CASE WHEN in WHERE clause

searched for this problem, but couldn't find a question for exactly this problem.
I have a stored procedure that fetches data from a large amount of tables.
In my SP I have a parameter indicating the ID. Default Value of that ID is zero.
I want to return all values regarding this parameter in my query, unless a value is provided.
SELECT mT.*
FROM myTable mT
(various JOINS)
WHERE
CASE #myParameter
WHEN 0 THEN 1 = 1
ELSE mT.ID = #myParameter
END
Unfortunately I get the error message "Incorrect syntax near '='".
Things that are fixed: It has to be a SP, I get just one parameter where I can set a default value in case it is not filled. If it is not filled this part of the where clause shall not apply (there are more statements in the WHERE clause.
If I did not see a question that contained this problem please give me a hint where to find it.
Best Regards and thanks in advance!
You don't need CASE:
SELECT mT.*
FROM myTable mT
(various JOINS)
WHERE
#myParameter= 0 OR mT.ID = #myParameter

Issue with 'NOT IN' statement in SQL

Can anyone please point out what is wrong with the following SQL statement:
SELECT DiaryType
FROM tblDiaryTypes
WHERE DiaryType NOT IN (SELECT NextDiary
FROM tblActionLinks
WHERE HistoryType = 'Info Chased');
Now the nested SELECT statement currently returns NULL because there are initially no entries in tblActionLinks, and I am wondering if that is the issue.
The outer SELECT statement if executed on its own does return all the Diary Types from tblDiaryTypes as expected. But when I add the nested SELECT statement to exclusde certain values, then the overall SQL statement returns empty!
Does this have something to do withthe fact that tblActionLinks is currently empty? If so, how can I amend my SQL statement to handle that possibility.
For SQL SERVER (you didn't specified sql engine) try with:
SELECT ISNULL(NextDiary, 0) ...
When no rows found all value is null then it will return 0
Are you sure there are no entries currently in tblActionLinks? If there are no entries in tblActionLinks, then outer query should return all records
Does this have something to do withthe fact that tblActionLinks is currently empty?
Yes... NULL doesn't being handled so good in SQL, Comparing a value to NULL is undifned try give for null a flag value like -999:
SELECT DiaryType
FROM tblDiaryTypes
WHERE DiaryType NOT IN (SELECT NVL(NextDiary, -999) -- <===
FROM tblActionLinks
WHERE HistoryType = 'Info Chased');
NVL(NextDiary, -999) means that if NextDiary IS NULL, replace the value with -999
docs
I would rewrite your query the following way:
SELECT DiaryType
FROM tblDiaryTypes
WHERE NOT EXISTS (SELECT NextDiary
FROM tblActionLinks
WHERE HistoryType = 'Info Chased'
AND NextDiary = DiaryType)
This ensures proper behaviour irrespective of ANSI_NULLS setting and you don't have to worry about properly choosing the magic value returned by ISNULL(NextDiary, 0) (what if you have DiaryType equal to 0 in tblDiaryTypes?)

Can Anyone explain why NULL is used in this query?

Also what will be the scenarios where this query is used
select * from TableA where exists
(select null from TableB where TableB.Col1=TableA.Col1)
As the query is in an EXISTS then you can return anything. It is not even evaluated.
In fact, you can replace the null with (1/0) and it will not even produce a divide by zero error.
The NULL makes no sense. It's simply bad SQL.
The exists clause is supposed to use SELECT *.
People make up stories about the cost of SELECT *. They claim it does an "extra" metadata query. It doesn't. They claim it's a "macro expansion" and requires lots of extra parse time. It doesn't.
The EXISTS condition is considered "to be met" if the subquery returns at least one row.
The syntax for the EXISTS condition is:
SELECT columns
FROM tables
WHERE EXISTS ( subquery );
Please note that "Select Null from mytable" will return number of rows in mytable but all will contain only one column with null in the cell as the requirement of outer query is just to check whether any row fall in the given given condition like in your case it is "TableB.Col1=TableA.Col1"
you can change null to 1, 0 or any column name available in the table. 1/0 may not be a good idea :)
It's a tacky way of selecting all records in TableA, which have a matching record (Col1=Col1) in TableB. They might equally well have selected '1', or '*', for instance.
A more human-readable way of achieving the same would be
SELECT * FROM TableA WHERE Col1 IN ( SELECT Col1 IN TableB )
Please, please, all ....
EXISTS returns a BOOLEAN i.e. TRUE or FALSE. If the result set is non empty then return TRUE. Correlation of the sub-query is important as in the case above.
i.e Give me all the rows in A where AT LEAST one col1 exists in B.
It does not matter what is in the select list. Its just a matter of style.

How to select an empty result set?

Want to improve this post? Provide detailed answers to this question, including citations and an explanation of why your answer is correct. Answers without enough detail may be edited or deleted.
I'm using a stored procedure in MySQL, with a CASE statement.
In the ELSE clause of the CASE ( equivalent to default: ) I want to select and return an empty result set, thus avoiding to throw an SQL error by not handling the ELSE case, and instead return an empty result set as if a regular query would have returned no rows.
So far I've managed to do so using something like:
Select NULL From users Where False
But I have to name an existing table, like 'users' in this example.
It works, but I would prefer a way that doesn't break if eventually the table name used is renamed or dropped.
I've tried Select NULL Where False but it doesn't work.
Using Select NULL does not return an empty set, but one row with a column named NULL and with a NULL value.
There's a dummy-table in MySQL called 'dual', which you should be able to use.
select
1
from
dual
where
false
This will always give you an empty result.
This should work on most DBs, tested on Postgres and Netezza:
SELECT NULL LIMIT 0;
T-SQL (MSSQL):
SELECT Top 0 1;
How about
SELECT * FROM (SELECT 1) AS TBL WHERE 2=3
Checked in myphp, and it also works in sqlite and probably in any other db engine.
This will probably work across all databases.
SELECT * FROM (SELECT NULL AS col0) AS inner0 WHERE col0 IS NOT NULL;
SELECT TOP 0 * FROM [dbo].[TableName]
This is a reasonable approach to constant scan operator.
SELECT NULL WHERE FALSE;
it works in postgresql ,mysql, subquery in mysql.
How about this?
SELECT 'MyName' AS EmptyColumn
FROM dual
WHERE 'Me' = 'Funny'
SELECT * FROM (SELECT NULL) WHERE 0
In PostgreSQL a simple
SELECT;
works. You won't even get any columns labeled 'unknown'.
Note however, it still says 1 row retrieved.