SQL Where statement with CASE variable - sql

Im sorry I do not have a complete query because my original is actually very long but I feel you may be able to spot where I have an error in my syntax. Basically I declare 2 variables and if one variable is blank I need the where statement to be where the field is not in the other variable.
Where dnCP_FromServiceDate >= '01/01/2016' And
dnCP_FromServiceDate <= '01/31/2016' And
dnCP_RecordStatus <> 'V'
AND CASE WHEN #inpDXIN = '' THEN
predxDiagnosisCode not in (#inpDXNOTIN)
ELSE predxDiagnosisCode IN (#inpDXIN)
END
Even if I could get a snippet of a query using a similar statement i can figure mine out but i cant find anything similar. Any help is greatly appreciated

In general, you don't want to use case in a where clause. Instead, just use regular boolean logic:
Where dnCP_FromServiceDate >= '2016-01-01' and
dnCP_FromServiceDate <= '2016-01-31' and
dnCP_RecordStatus <> 'V' and
( (#inpDXIN = '' and predxDiagnosisCode <> #inpDXNOTIN) or
(#inpDXIN <> '' and predxDiagnosisCode IN (#inpDXIN)
)
Notes:
Use ISO/ANSI standard date formats. Much less ambiguous.
IN (#var) is the same as = #var. You cannot pass an in list through a variable. If you need that functionality, then ask another question.
Most dialects of SQL do not allow boolean expressions to be returned from a case. The above gets around this "limitation".

Related

SQL Using CASE to Apply WHERE [duplicate]

This question already has answers here:
SQL Server : check if variable is Empty or NULL for WHERE clause
(6 answers)
Closed 6 months ago.
I'm not sure if CASE is what I actually need to use here, but basically what I am trying to do is apply "WHERE ba.batchid = #batchId" but only if #batchId is not null.
Basically something like this, but this gives an error around the ba.batchid = '2' area ('2' is what the #batchId would come out to).
CASE WHEN '2' != '' THEN ba.batchid = '2' ELSE null END
It helps to think of Case statements as a scalar value. The problem you are experiencing is caused by doing a comparison within the case statement. Basically, you need to pull the comparison out of the case statement.
I'm not sure of the logic you are trying to use, but the following syntax should be correct.
CASE WHEN '2' != '' THEN ba.batchid ELSE null END = '2'
Note that the = '2' is moved to the end. This way, the case statement will return batchid or null depending on the WHEN statement. This value is then compared to '2'.
Try this:
WHERE NULLIF(#batchId, '') IS NOT NULL AND ba.batchid = #batchid
First condition avoids empty('') as well as NULL with #batchid. Second will match the table value.
Take it out of the SELECT part of your statement entirely and put it in the WHERE clause (after FROM)
WHERE ba.batchid = #batchId
AND ba.batchid IS NOT NULL
Note that the AND ba.batchid IS NOT NULL is not necessary here as the first line will filter any nulls. However there are versions of SQL where this is not the case and retaining it in the query still works, hence I have left it in.

Setting BIT variable using CASE statements

I'm in the middle of a migration that uses some reporting elements from Crystal and attempting to convert what existed previously into SQL. It looks to use VB scripting but I can't figure out how to make the switch over.
Initially I'd assume a CASE WHEN statement would suffice but I can't determine the right logic behind the query.
Sample of the VB below:
Dim HasValue As Boolean
If isnull({Reference.Shallow}) Then
HasValue=False
formula="MISSING"
Else
HasValue=True
End If
I am aware that IF does exist in SQL Server but when researching it, people tend to stray away from it as CASE WHEN does the same?
I have some psuedo that I'd imagine should work in the same way but this does not resolve as you cannot set a variable within a CASE WHEN statement (I believe):
DECLARE HasValue BIT
CASE WHEN Reference.Shallow IS NULL
THEN SET #HasValue = 1
ELSE SET #HasValue = 0
END AS Shallow
What would be the most appropriate way of doing this within SQL?
You must use this code snippet
DECLARE #HasValue BIT
SELECT #HasValue=CASE WHEN Shallow IS NULL THEN CAST(1 AS BIT) ELSE CAST(0 AS
BIT) END FROM Reference.Shallow
CASE returns a scalar value, not a operation or boolean result. You set the value of the variable to the result of the CASE:
SET #HasValue = (SELECT CASE WHEN R.Shallow IS NULL THEN 1 ELSE 0 END
FROM dbo.Reference R
/*WHERE...? */);

access statement convert to Sql

how can I convert to T-Sql this one?
IIf([ESSValue]<>0,Int([ESSValue]*100),"")
I think the following pretty much does what you want:
select coalesce(cast(EssValue * 100 as int), 0)
Here is the thinking. The comparison to zero is unimportant, because 0 times any value is going to be zero. The iif() returns an integer (I think) because the "then" argument is an integer; the empty string gets converted to zero.
I'm not 100% certain about the last statements with regard to MS Access, but that is how iif() works in SQL Server.
I should add. Although I don't approve of iif() for conditional expressions (because case is the standard and more powerful), SQL Server does support it. So you could write:
IIf([ESSValue]<>0, cast([ESSValue]*100 as int), '')
Note: As I mentioned earlier, the '' will be converted to 0.
CASE WHEN ESSValue <> 0
THEN CAST(ESSValue * 100 AS INT)
ELSE NULL
END as fieldname
For case expression the default is NULL if doesn't meet any condition, so you dont really need the ELSE condition

SQL query with a CASE statement

I am still learning much about SQL queries but found myself stuck on this. I understand I could break this Query into two queries to get the desired functionality, but i would like to do it in one if possible. My problem lies within the Case clause. i have a condition if the in and out columns are between the selected date range, i want to do myColumnValue + .5 else keep it the same. myColumnValue is a double. The problem is, when i add 'myColumnValue + some constant' to the THEN and Else Clause, it makes the update have now effect on the row, but when i remove it and have only constants in it... it works fine. I am using SQL server 2008. I know I am probably missing some part of the query where I have to reinitialize the myColumnValue as a varible, but I am unsure how to do this. If anyone can give me some direction if keeping this into one query, or if there is an easier way to do this without cases, any guidance would be greatly appreciated. Thanks in advance.
UPDATE myTableName
SET myColumnValue=
(CASE
WHEN((In <= '12/1/2011' ) AND (Out >= '12/7/2011' ))
THEN(myColumnValue + .5 )
ELSE(myColumnValue)
END)
WHERE ID = 'someIndex'
The right way is moving case condition to where clause:
UPDATE myTableName
SET myColumnValue=myColumnValue + .5
WHERE ID = 'someIndex'
AND ([In] <= '12/1/2011' )
AND ([Out] >= '12/7/2011' )

Regex: does a SQL statement include a WHERE clause?

I need a regex that will determine if a given SQL statement has a WHERE clause. My problem is that the passed SQL statements will most likely be complex, so I can not rely on just the existence of the word WHERE in the statement.
For example this should match
SELECT Contacts.ID
, CASE WHEN (Contacts.Firstname IS NULL) THEN ''
ELSE CAST(Contacts.Firstname AS varchar)
END AS Firstname
, CASE WHEN (Contacts.Lastname IS NULL) THEN ''
ELSE CAST(Contacts.Lastname AS varchar)
END AS Lastname
, CASE WHEN (tbl_ContactExtras.Prequalified=-1 OR
tbl_ContactExtras.Prequalified IS NULL) THEN ''
WHEN tbl_ContactExtras.Prequalified=0 THEN 'No'
WHEN tbl_ContactExtras.Prequalified=1 THEN 'Yes - Other'
WHEN tbl_ContactExtras.Prequalified=2 THEN 'Yes'
ELSE CAST(tbl_ContactExtras.Prequalified AS varchar)
END AS Prequalified
FROM contacts
LEFT JOIN tbl_ContactExtras
ON tbl_ContactExtras.ContactID = Contacts.ID
WHERE (Contacts.Firstname LIKE 'Bob%')
and this should not match:
SELECT Contacts.ID
, CASE WHEN (Contacts.Firstname IS NULL) THEN ''
ELSE CAST(Contacts.Firstname AS varchar)
END AS Firstname
, CASE WHEN (Contacts.Lastname IS NULL) THEN ''
ELSE CAST(Contacts.Lastname AS varchar)
END AS Lastname
, CASE WHEN (tbl_ContactExtras.Prequalified=-1 OR
tbl_ContactExtras.Prequalified IS NULL) THEN ''
WHEN tbl_ContactExtras.Prequalified=0 THEN 'No'
WHEN tbl_ContactExtras.Prequalified=1 THEN 'Yes - Other'
WHEN tbl_ContactExtras.Prequalified=2 THEN 'Yes'
ELSE CAST(tbl_ContactExtras.Prequalified AS varchar)
END AS Prequalified
FROM contacts
LEFT JOIN tbl_ContactExtras
ON tbl_ContactExtras.ContactID = Contacts.ID
Those are examples of some of the simpler statements: a statement could have up to 30 CASE statements in it, or it could have none at all.
I need to programmatically add WHERE parameters, but doing this correctly requires knowing whether a WHERE clause is already present.
Any idea on a regex that would work for this? If not, any other ideas on how to tell the two apart?
Thanks,
This is not possible, since a WHERE clause may be arbitrarily nested inside the FROM clause.
This may not catch all cases but you may find you can catch most of them just by finding the last from and the last where in the statement.
if the where is after the from, then it has a where clause. If the where is before the from (or there is no where at all), then no where clause exists.
Sometimes, it's okay to leave restrictions or limitations in your code, as long as they're properly documented.
For example, I've worked on a project before that parsed SQL and we discovered it didn't handle things like between:
where recdate between '2010-01-01' and '2010-12-31'
Rather than spend a bucket-load of money fixing the problem (and probably introducing bugs on the way), we simply published it as a restriction and told everyone they had to change it to:
where recdate >= '2010-01-01'
and recdate <= '2010-12-31'
Problem solved. While it's good to keep customers happy, you don't have to cater to every whim :-)
Other than that, you need an SQL parser, and SQL is not a pretty language to parse, trust me on that one.
Are all of the joins the same? If so you could find the index of all or part of the FROM statement (perhaps using a regex to be tolerant of slight differences in syntax and whitespace) and then look for the occurrence of the word WHERE after that index.
In general you would be better off using a parser. But if this is just a one off thing and the statements are all fairly similar then the above approach should be okay.
Regex is not designed to do this. Parsing SQL properly requires matching balanced parentheses (and other matching pairs, such as quotes), something regex is not designed to do (and pure regex isn't even equipped to; PCRE can but it's not pretty).
Instead, just write a basic state machine or something to parse it.
What's the problem you're trying to solve? Are you trying to determine if it's safe to add constraints to these existing queries?
For example, if you've got this query
...
where foo = 'bar'
then you know it's safe to add
and bat = 'quux'
but if you don't have a WHERE clause already, then you have to do it as
where bat = 'quux'
Is that the problem you're trying to solve? If so, can you make every SQL query you're working with have a WHERE clause by adding a "WHERE 0=0" to those queries that don't have one? Then you know in your post-process phase that every query already has one.
This is just a guess, of course. Your question sounded like that might be the larger issue.