How to use conditional different columns in WHERE clause? - sql

I want to use completely different conditions in a WHERE-clause in an SQL Server 2014 query, not just change the parameter.
I have the following clause
WHERE (dbo.SecurityCheckUserInADGroups.CWID = #cwid2) AND (dbo.SecurityCheckUserInDatabaseRoles.Server = #server)
If the variable #cwid2 is NULL or empty I'd like to replace the whole first part of the AND-Statement with
dbo.SecurityCheckLDAPGroupName.DatabaseUserName = #role2
So here not only the parameter but also the column changes.
I tried If, Case and Iif with something like this, but it isn't accepted:
(IIF (LEN(#cwid1) > '0, 'dbo.SecurityCheckUserInADGroups.CWID = #cwid2','dbo.SecurityCheckLDAPGroupName.DatabaseUserName = #role2'))
It keeps telling me "An expression of non-boolean type specified in a context where a condition is expected"
Any ideas how I can solve this?

Just use basic logic:
WHERE ((#cwid <> '' AND dbo.SecurityCheckUserInADGroups.CWID = #cwid2) OR
(COALESCE(#cwid, '') = '' AND dbo.SecurityCheckLDAPGroupName.DatabaseUserName = #role2)
) AND
(dbo.SecurityCheckUserInDatabaseRoles.Server = #server)

The most general solution would be
Where (#var is null and col1=val1)
Or (#var is not null and col2=val2)
Because query optimizers can sometimes choke on OR, I tend to look for other solutions when performance could be an issue (large data sets, etc.) but the above might be worth trying first.
If you do need something more specific, the trick to iif logic is that it returns a value to compare, not a predicate to evaluate. You could do something like
Where col1 = iif(#var is null, val1, col1)
And col2 = iif(var is null, col2, val2)
The idea here is that your "don't care" cases - like the value of col2 when var is null - resolve as "always true". But there are cases (like when col1 or col2 could be NULL) where this specific solution Will fail.
Which is why the first approach is the most general

WHERE CASE WHEN ISNULL(#cwid2,'') <> '' THEN
dbo.SecurityCheckUserInADGroups.CWID = #cwid2 ELSE
dbo.SecurityCheckLDAPGroupName.DatabaseUserName = #role2
END
AND dbo.SecurityCheckUserInDatabaseRoles.Server = #server

Related

Postgres: handling null in where clause

Using Birt reporting which allows injecting parameter in a query as follow:
SELECT *
FROM foo
WHERE bar = ?
The question mark comes from a drop down list. Among these values, 'All' can be selected, meaning there are no WHERE clause.
Is there a way to have conditional value in the WHERE clause such as below or an equivalent ?
WHERE
CASE WHEN ? IS NULL
THEN 1=1
ELSE bar = '%'
END
you can try something like:
SELECT *
FROM foo
WHERE COALESCE(bar, '') = COALESCE(?, bar, '')
so, if argument is null - column will be compared with itself, which is almost always returns true, except weird logic around null values, this is why we need coalesce on both sides of equation

SQL: Is there a way for me to call another table.field when my initial table.field = NULL?

Morning All! Essentially, I found out that a potential table.field I'd like to use may not have the information I want, so, I might have to look into a separate field. My below thought process is:
If table.field1 = NULL then pull the value from table.field2. If table.field2 = NULL then state "No Phone"
My current SQL statement in the select, cause it's in a certain format, is:
substring(view_episode_summary_current.patient_home_phone, 1, 3) || ' ' || substring(view_episode_summary_current.patient_home_phone, 5, 8)
Above is let's say table.field1. I'm assuming I'll need to create a CASE statement right? I just didn't know how long it could be?
(case when view_episode_summary_current.patient_home_phone = NULL then table.field2)
But I don't know how to get it to evaluate if table.field2 = null and display the value.
In many databases, you can use coalesce() to implement that kind of logic:
coalesce(t1.field1, t2.field2) as myfield
coalesce() returns the first non-null value across its arguments. So it gives you t1.field1 if it is not null, else it falls back on t2.field2. If both are null, you get a null value as a result.
You could also use a case expression - there is no benefit as compared to colaesce(), but this can handle more complex cases than just nullity checks
case
when t1.field1 is not null then t1.field1
when t2.field2 is not null then t2.field2
end as myfield
case stops on the first branch where the condition is fulfilled. If no branch matches, it returns null - you can put an else branch at the end of your code to return something else.
Note that both techniques requires both fields to have similar data types.
You do not show your actual query so I cannot show how to use that in your code.

Oracle SQL placeholder for everything in WHERE clause

I am trying to write a SQL query with a WHERE clause that does not actually filter anything.
import cx_Oracle
condition = []
#condition = ['a', 'b']
query = ("""
SELECT *
FROM table
WHERE var = {}""".format(tuple(condition)))
with cx_Oracle.connect(dsn=tsn), encoding="UTF-8")) as con:
df = pd.read_sql(con=con, sql=query)
Disclaimer: Still a bit new to SQL. I appreciate corrections of terminology
Edit:
This is often handled using logic like this:
where col = :input_val or :input_val is null
If you don't want to have the WHERE clause filter anything then it needs to contain a condition which is always true; something like
SELECT *
FROM table1
WHERE var = var OR
var IS NULL
db<>fiddle here
If you need to use an index and the column value is not nullable then you'll want to use the NVL trick. I don't know why, but Oracle has better optimizations for NVL than for the ...OR A IS NULL expression.
SELECT *
FROM table
WHERE nvl(anyvalueofvar1, var) = var;
See my answer here for an example of the better execution plan generated by this different syntax.
(I said "and the column value is not nullable" because NULL = NULL is not true in Oracle, so the NVL expression won't work if the column has nulls. I usually hate these cryptic syntaxes with weird behavior, but they are sometimes necessary for performance.)

How can I skip the then part of a case statement in SQL

I have a situation in which I need to do nothing if these conditions are met in the when part and assign value otherwise. I am using the case when <expression> then <some operation/assignment> end in my SQL.
I want to skip this then part as this is a special condition and I do not want any assignment here just pass by to the else
(case
when '$usertype_id' = 'null' or '$usertype_id' = 0 or '$usertype_id' = 999
then //do nothing
else x.usertype_id = '$usertype_id'
end)
Please let me know how can I achieve this. Thank you.
You don't. You use conditional logic without a case expression:
('$usertype_id = 'null' or '$usertype_id = 0 or '$usertype_id = 999) or
(x.usertype_id = '$usertype_id')
More importantly, I would strongly, strongly encourage you to use parameters instead of munging query strings with parameter values.

SQL Error (4145): An expression of non-boolean type specified in a context where condition is expected, near '('

Using the below statement to check whether a field is null and if it is null then I need to show "Not Yet Approved" message. Otherwise I would like to get a concatenated result of some fields which is mentioned below.
select
iif(isnull(AppByENo1,'true'),'Not Yet Approved',AppByENo1+AppByDesg1+AppByDate1) as result
from myDB
where (E_No = '25')
But getting the above mentioned error while trying to run the sql query.
Please advice where I am making mistake and how to tackle this issue.
try this:
select
iif(isnull(AppByENo1,'true') = 'true','Not Yet Approved',AppByENo1+AppByDesg1+AppByDate1) as result
from myDB
where (E_No = '25')
Use CASE Statement in SELECT clause instead of IFF :
SELECT CASE WHEN ISNULL(AppByENo1,'true') = 'true' THEN 'Not Yet Approved'
ELSE AppByENo1+AppByDesg1+AppByDate1 END as result
FROM myDB WHERE E_No = '25'
Since concatenating null values yields null (providing you're leaving appropiate settings turned on, which you should), you can just use a simple coalesce to replace the null if necessary:
select
COALESCE(AppByENo1+AppByDesg1+AppByDate1,'Not Yet Approved') as result
from myDB
where (E_No = '25')
If you insist on the iif approach, I'd favour:
iif(AppByENo1 is null,'Not Yet Approved',AppByENo1+AppByDesg1+AppByDate1)
E.g. an actual null test, rather than trying to identify a sentinel string that cannot appear naturally and performing a string comparison after isnull.