SQL - CASE expression inside WHERE - sql

I read about using the CASE expression inside the WHERE clause here:
http://scottelkin.com/sql/using-a-case-statement-in-a-sql-where-clause/
I'm trying to use this to filter results from my select statement, based on a contract number which will be passed in by the user's application. My code currently throws an error of 'Invalid parameter' no matter what is passed in. I verified SELECT/FROM are working fine, as where as a WHERE clause without a CASE expression. Here is my code.
WHERE (CASE WHEN #ContractNo = 0 THEN #ContractNo ELSE #ContractNo END =
tblContracts.ContractNo)
The redundancy of the code is for troubleshooting purposes, I'm planning on using wildcard filtering on the CASE later. I'm focusing on getting the syntax down right now. I believe this should return all records for which the parameter matches the contract number stored in the table. Any help or advice would be greatly appreciated.

Are you sure you want to do this? Your case statement ALWAYS returns #ContractNo. I think what you are looking for is this:
where
case #ContractNo
when 0 then tblContracts.ContractNo
else #ContractNo
end = tblContracts.ContractNo
The filter above says "give me the contract where the ContractNo equals the parameter, or all of them if the parameter is 0.
The previous filter only filtered where the contract number field is exactly equal to the parameter.
Regardless, you should do this instead:
where #ContractNo = 0 or #ContractNo = tblContracts.ContractNo
The logic is much easier to understand, and on top of that (don't quote me on this), the optimizer probably will work better outside of the case statement.

After reading your explanation, there's a better way to do this without CASE:
WHERE #ContractNo = 0 OR tblContracts.ContractNo = #ContractNo
This will return only matching contract numbers, unless #ContractNo is 0, in which case it will return all records.
Edit: I've just noticed that casperOne proposed the same thing. I didn't see that. Big up yourself.

Try leaving out the parentheses which are in the wrong place anyway - the right one should be after "END".

Maybe you forgot to declare #ContractNo? Is it comparable to 0 and to tblContracts.ContractNo?

Recursive's post solved my issue precisely.
I saw complaints about the clarity of my original post. In the future, what can I do to make what I'm saying more straight forward? I'm not used to phrasing questions about code, and apologize for any muddled things it had. Did I just need to provide the extended details like in my 2nd post?
Thanks again for all the help.

Move your close parenthesis to before the = like so:
WHERE (CASE WHEN #ContractNo = 0 THEN #ContractNo ELSE #ContractNo END)=tblContracts.ContractNo
I fail to see what this case statement will do though... you're returning the same thing in the event the #ContractNo = 0 or if it's not...
The correct syntax is:
Select...
...
Where(
Case
When <Condition>
Then <Return if true>
Else <Return if false>
End
) = <Whatever is being matched to the output of the case statement>
Regardless of the syntax though, your example doesn't make a lot of sense, if you're looking for all items that match or have a Contract Number of 0, then you would do:
Select...
...
Where (
#ContractNo = 0 Or
#ContractNo = tblContracts.ContractNo
)
Which seems to make far more sense than what you're attempting to use the case statement for.
Edit: I must've misread the question slightly - the missing param usually means that the parameter (in this case #ContractNo) is not declared in the scope of your query/procedure. But someone already pointed that out, so I can't take any credit for that.

The reason for the case statement, including the whole "If it's 0, give the parameter, and otherwise, just give the parameter" was to test it to try to get the syntax right. Originally, I had tried saying "If it's 0, then pass in '%', to return every value. The code I posted in there was because I kept getting 'Invalid Parameter' and figured there must be something wrong with my syntax. When I separated it into basic parameter matching like so,
WHERE #ContractNo = tblContracts.ContractNo
it returned records fine. Let me explain a bit more.
I'm pulling from a bunch of different tables, and filtering the content with information not included in the select statement (i.e. tblContracts is not having information pulled from it by Select, it's only used in Where). The user will select from a combo box which will have the different contract numbers, as well as a default value of 'All'.
I'm going to have an event for when the index of the combo box changes. If it's 'All', 0 will be passed in as a parameter and I want no filtering done. Otherwise, I just want the information for that contract number (the reason for Else #ContractNo).

Don't you mean something like this?
SELECT *
FROM tblContracts
WHERE
CASE
WHEN tblContracts.ContractNo = 0 THEN #ContractNo
ELSE tblContracts.ContractNo
END = tblContracts.ContractNo
Where #ContractNo is variable of the same datatype as tblContracts.ContractNo

Why do you even need a case statement?
WHen #ContractNo = 0 then ( 0 = tblContracts.ContractNo)
else #ContractNo then (#ContractNo = tblContracts.ContractNo)
This makes no sense since you could simply write this as
Where #contractNo = tblContracts.contractNo

Is the contract number actually a numeric or is it a string that always happens to be a numeric. Check your data types between the table and the parameter and the CASE statement (for example, "= 0" or "= '0'")

This syntax should work (it does in Oracle)
WHERE CASE WHEN tblContracts.ContractNo = 0
THEN #ContractNo
ELSE tblContracts.ContractNo
END = tblContracts.ContractNo

when you say:
I'm pulling from a bunch of different tables, and filtering the content with information not included in the select statement (i.e. tblContracts is not having information pulled from it by Select, it's only used in Where). The user will select from a combo box which will have the different contract numbers, as well as a default value of 'All'.
Then it sounds to me that should have an "Where exists" clause. since your not pulling any info out of that table?!

Related

SQL What does IF evaluate to for NULL

Hi this is a pretty basic question, but I am not able to find a definitive answer to it.
What does IF evaluate to for NULL in SQL ? What will happen in following code if fieldXYZ were NULL
IF fieldXYZ=SomeValue
//do something
ELSE
//do something else
Update:
I have found one result which suggests that NULL can be considered as falsy
https://technet.microsoft.com/en-us/library/ms182587(v=sql.110).aspx
First of all, I think your if..else statement is incomplete as you are not defining any expression for your column fieldXYZ. Generally, when you write an if..else statement, you would want to write an expression that compares your column value with something. You can explicitly check for null values if you want to handle them. Here is a gist of that syntax:
--This handles null check explicitly
IF fieldXYZ IS NOT NULL AND fieldXYZ = 'somevalue'
//do something
ELSE
//do something else
Also, if the fieldXYZ is passed a NULL value in the above statement, then the first condition is not met, so the else condition applies immediately in that scenario.Hope this helps!
(I am reluctant to answer my own question, but in absence of any solution, reposting my comment as answer)
Apparently the right way is to consider NULL as falsy.

CASE WHEN THEN (Return Column) ELSE END

I'm very new to SQL and mainly use Excel, I am using Oracle BI and need to add a column that does the following.
=IF(A1="EG123456",B1,"")
I've got this far.
CASE WHEN "table1"."clientnumber" = 'EG123456'
THEN "table1"."BookingID"
ELSE ''
END
it accepts the formula but when I go to view the results it says "View Display Error"
It seems likely that BookingID might be a type other than CHAR/VARCHAR; for example perhaps it's a numeric field? All possible returns form a CASE must be of compatible type.
Would it work to use ELSE NULL instead of ELSE ''? NULL will be compatible with all types and will come across as "blank"; but depending on how you further process the results, you may need to beware of the "strange" rules for handling NULL values.
The other option might be to cast BookingID to a CHAR type. e.g if you know that it's never more than 20 characters, you could say THEN CAST(BookingID AS CHAR(20))

Netsuite CASE WHEN expression in custom search is returning "invalid expression"

I am new to writing CASE expressions in NetSuite. I have inserted the following expression in a formula field of a custom search.
CASE WHEN {item.custitem_custid}=05 OR {item.custitem_custid}=12 THEN
({item.custitem_margin}/2)
ELSE
({item.custitem_margin}/3)
END
and getting "invalid expression as a result. I am attempting to divide the margin field value by 2 if the WHEN case is true and divide by 3 if not true. Anybody have any idea as to what is wrong with my formula?
I think you need to add parentheses:
CASE WHEN ({item.custitem_custid}=05 OR {item.custitem_custid}=12) THEN
({item.custitem_margin}/2)
ELSE
({item.custitem_margin}/3)
END
I agree with egrubaugh360 that the syntax is fine and likely the joins are not working correctly. In your forumula, just double-check the "item." portion and see what you can do.
I also agree with the NVL() recommendation, but I can also see that your denominator is 2 and 3, respectively, therefore the NVL() function won't do anything to help. PLEASE DO USE NVL() every time your denominator is an unknown value, such as from a field on your record/transaction.

VB.net Strange Conditional Statement (IF)

Was wondering if someone could lend me their expertise. Pretty new to Vb.net and have come across this conditional statement in one of our products. Could someone please confirm the validity of the statement and explain what's going on here? I've tried numerous searches, but I cannot find anything related.
If (IsDBNull(dr("someID")), "0", dr("someID")) = someID.ToString() Then
I have changed the "id" value names as it's code from a commercial product, but the ID's used were all the same variable (ints).
Thanks for any input you can offer on this!
Joe
PS: The reason I can't check this at run time is because of how the product operates.
It is an inline If statement
If(condition,iftrue,iffalse) if condition is true evaluate and return iftrue else iffalse
The If operator in VB.NET 2008 acts as a ternary operator.[ REFERENCE]
Example:
Dim foo as String = If(bar = buz, cat, dog) 'Condition satisfied then it'll return cat else dog.
The statement is checking to see if the dr("SomeID") equals the value someID.ToString. The reason the If is required is because you need to check if the dr("someID") Is Null. If it is 0 is used instead which presumably should not be equal to someID.
It is the same as doing the following:
If Not IsDBNull(dr("someID")) Then
If dr("someID").ToString = someID.ToString Then
End If
End If
I would suggest that something like this would be more appropriate (checking integer values instead of comparing strings)
If(IsDBNull(dr("someID")), 0, CInt(dr("someID"))) = someID Then
I would also suggest Turning Option Strict On as the code you posted should not compile!

How do i make multiple variations of a string in vb.net?

I made this one code and I was wondering how I can make it more effective with little work.
This is an example of one of the if then else statements I put in:
If lblQuestion.Text = "anti-" Then
lblCorrectAnswer.Text = "against, opposed to, preventive; used as a prefix"
If txtPlayersAnswer.Text = "against, opposed to, preventive" Then
lblRight.Text = "Correct"
Else
lblRight.Text = "Wrong!"
End If
End If
I was wondering if it was possible to make multiple variations for the statement
If txtPlayersAnswer.Text = "against, opposed to, preventive" Then
For example: Instead of having to code out each possible variation for that line of code is there a way to make that one line of code have all the possible variations, and if so how?
Thank you in advance.
Too many assumptions of user input for me , but
pseudo code
Given answers was an array of ["against"],["opposed to"],["preventative"]
then you could do something like
count = 0;
foreach(answer in answers)
if txtPlayersAnswer.Contains(answer) count++
case sensitive will be an issue as would be answer like "not against"
Me I'd get the user to enter each potential answer separately instead of having to rely on them entering them in a format you knew how to chop up.