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

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.

Related

SQL case expression with where condition

how can I arrange the case expression of sql in the correct format as I am getting errors.
I am trying to make a condition if the field date of leaving is not null display left otherwise display active
SELECT DISTINCT
PEO.PEOPLE_ID AS [PEOPLE_ID]
,PEO.EMPLOYEECLOCKNO AS [EMPLOYEENUMBER]
,ISNULL(CONVERT(VARCHAR(50),PEO.DATEOFJOIN,103),'') AS [DATEOFJOIN]
--,ISNULL(PEO.DISPLAYSTATUS,'') AS [DISPLAYSTATUS]
,CASE
When ISNULL(PEO.STATUS,'' ) = 'A'
Then 'ACTIVE'
ELSE 'LEFT' WHERE PEO.DATEOFLEAVING <> NULL
END as [STATUS]
INTO #BSP_EMPLOYEEDETAILS
Thank you for your help.
I am trying to make a condition if the field date of leaving is not null display left otherwise display active
CASE WHEN PEO.DATEOFLEAVING IS NULL THEN 'ACTIVE' ELSE 'LEFT' END
(I prefer to make boolean checking positive-feeling rather than negative-feeling, but if you want it negative...)
CASE WHEN PEO.DATEOFLEAVING IS NOT NULL THEN 'LEFT' ELSE 'ACTIVE' END
Note well HoneyBadger's comment; you should only compare something to null using IS NULL or IS NOT NULL - the result of a null right operand with any non-IS operator, is null:
NULL IS NULL --true
NULL IS NOT NULL --false
NULL = NULL --null, which eventually will (probably) be processed as false
NULL <> NULL --null, which eventually will (probably) be processed as false
NULL != NULL --null, which eventually will (probably) be processed as false
NOT(NULL = NULL) --null, which eventually will (probably) be processed as false
I say "eventually" because it's important; null spreads. If you look at the last case, NULL=NULL is NULL, which then becomes NOT(NULL) which is also NULL. If NULL=NULL instantly became FALSE then NOT(NULL=NULL) would be NOT(FALSE) which would be TRUE. The fact that the null spreads throughout the entire set of operations you subject it do, popping out at the end and then being interpreted as false is something that may be advantageous, but always something you should be aware of...
Of course if the thing that receives it is intended for processing NULL, like COALESCE(NOT(NULL=NULL), 'it was null') then it will receive a null (and in this case would output 'it was null') but generally when youre using it in a boolean context like CASE WHEN NOT(mycolumn=NULL) THEN... or WHERE NOT(mycolumn=NULL) the NULL it becomes is received by case when/where and interpreted as false.
It's probably worth pointing out that SQLServer doesn't support booleans in these sort of contexts so you wouldn't get away with using a coalesce like that, or even the NOT(NULL=NULL) example but if you want to experiment to sound out your knowledge, MySQL is a lot more forgiving, and will allow queries like:
select case when (NOT(x = NULL)) IS NULL THEN 't' ELSE 'f' end
from (select null as x)y
select case when (NOT(x = NULL)) IS UNKNOWN THEN 't' ELSE 'f' end
from (select null as x)y
SQLServer expects you to make your null determinations sooner, and doesn't let you bandy around with things that it can see have become null/unknown
Footnote about UNKNOWN; it's generally treated (in the spec, even) as synonmous with a boolean NULL - it's talked about in the truth table sense as the third value in a tri-state boolean logic, but DBs generally make for interchangeable use if they support UNKNOWN as a keyword. For me, personally, I like one-less-thing-to-remember; you can learn how NULL behaves and achieve logically consistent results by applying those simple rules: IS NULL, IS NOT NULL, anything else becomes NULL which then nulls everything it touches

Check column IS NULL not working in Case Expression

I am trying to check a column which belongs to View "IS NULL" and it works good with select statement:
SELECT TOP (1000) [Invoice_Number]
,[Invoice_Date]
,[Invoice_Amount]
,[Invoice_CoCd]
,[Invoice_vendor]
,[Invoice_PBK]
,[Invoice_DType]
,[Invoice_DueDate]
,[Invoice_ClgDate] FROM [dbo].[viewABC] where Invoice_PBK IS NULL
Now I have an update statement, where I need to update a column in a table based on NULL in VIEW:
UPDATE cis
SET
cis.InvoiceStatus =
(
CASE
WHEN RTRIM(LTRIM(imd.[Invoice_PBK])) IS NULL THEN
'HELLO'
WHEN RTRIM(LTRIM(imd.Invoice_DType)) = 'RD'
THEN '233' END)
FROM
[dbo.[tblABC] cis,
[dbo].[viewABC] imd
WHERE [condition logic]
These is no issue with where condition, the IS NULL in the CASE expression causing the problem.
Can someone help please?
You may want to just test your Logic piece by piece.
Try
SELECT ISNULL(RTRIM(LTRIM(imd.[Invoice_PBK])),'Hey Im Null')
FROM
[dbo].[tblABC] cis,
[dbo].[viewABC] imd
WHERE [condition logic]
See if you get that String value on your returned column(s) from the Query. Then, build from there. It could be something as simple as the JOIN. Which I'm not a fan of that old syntax but, without more info on this table other than [conditions]. It's hard to just guess an answer for you. You have no detailed evidence that helps us. It very well could be your conditions but, you're saying "condition logic" and that does nothing for the group on this thread.
Looking at this expression:
cis.InvoiceStatus =
CASE
WHEN RTRIM(LTRIM(imd.[Invoice_PBK])) IS NULL THEN
'HELLO'
WHEN RTRIM(LTRIM(imd.Invoice_DType)) = 'RD' THEN
'233'
END
And this symptom:
CIS.InvoiceStatus gets updated with NULL
The obvious conclusion is neither WHEN condition is met, and therefore the result of the CASE expression is NULL.
Maybe you wanted this, which will preserve the original value in that situation:
cis.InvoiceStatus =
CASE
WHEN RTRIM(LTRIM(imd.[Invoice_PBK])) IS NULL THEN
'HELLO'
WHEN RTRIM(LTRIM(imd.Invoice_DType)) = 'RD' THEN
'233'
ELSE
cis.InvoiceStatus
END
Or maybe you wanted this, to also match an empty string value:
cis.InvoiceStatus =
CASE
WHEN NULLIF(RTRIM(LTRIM(imd.[Invoice_PBK])),'') IS NULL THEN
'HELLO'
WHEN RTRIM(LTRIM(imd.Invoice_DType)) = 'RD' THEN
'233'
END
It's also worth pointing out the two WHEN conditions are looking at two different columns.
Finally, it may be worth a data clean-up project here. Needing to do an LTRIM() will break any chance of using indexes on those fields (RTRIM() is slightly less bad), and index use cuts to the core of database performance.

Simple where clause condition involving NULL

I have a query that needs to exclude both Null and Blank Values, but for some reason I can't work out this simple logic in my head.
Currently, my code looks like this:
WHERE [Imported] = 0 AND ([Value] IS NOT NULL **OR** [Value] != '')
However, should my code look like this to exclude both condition:
WHERE [Imported] = 0 AND ([Value] IS NOT NULL **AND** [Value] != '')
For some reason I just can't sort this in my head properly. To me it seems like both would work.
In your question you wrote the following:
have a query that needs to exclude both Null and Blank Values
So you have answered yourself, the AND query is the right query:
WHERE [Imported] = 0 AND ([Value] IS NOT NULL AND [Value] != '')
Here is an extract from the ANSI SQL Draft 2003 that I borrowed from this question:
6.3.3.3 Rule evaluation order
[...]
Where the precedence is not determined by the Formats or by
parentheses, effective evaluation of expressions is generally
performed from left to right. However, it is
implementation-dependent whether expressions are actually evaluated left to right, particularly when operands or operators might
cause conditions to be raised or if the results of the expressions
can be determined without completely evaluating all parts of the
expression.
You don't specify what kind of database system you are using but the concept of short-circuit evaluation which is explained in the previous paragraph applies to all major SQL versions (T-SQL, PL/SQL etc...)
Short-circuit evaluation means that once an expression has been successfully evaluated it will immediately exit the condition and stop evaluating the other expressions, applied to your question:
If value is null you want to exit the condition, that's why it should be the first expression (from left to right) but if it isn't null it should also not be empty, so it has to be NOT NULL and NOT EMPTY.
This case is a bit tricky because you cannot have a non empty string that is also null so the OR condition will also work but you will do an extra evaluation because short-circuit evaluation will never exit in the first expression:
Value is null but we would always need to check that value is also not an empty string (value is null or value is not an empty string).
In this second case, you may get an exception because the expression [Value] != '' may be checked on a null object.
So I think AND is the right answer. Hope it helps.
If the value was numeric and you didn't want either 1 or 2, you would write that condition as
... WHERE value != 1 AND value != 2
An OR would always be true in this case. For instance a value of 1 would return true for the check against 2 - and then the OR-check would return true, as at least one of the conditions evaluated to true.
When yu also want to check against null values, the situation is a bit more complicated. A check against a null value always fails: value != '' is false when value is null. That is why there is a special IS NULL or IS NOT NULL test.

How to use conditional different columns in WHERE clause?

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

When or why is equals not the opposite of not equals in a SQL query?

In a table containing five records where the Toppings value is "Chocolate", two of them have the value "Yes" in the MaraschinoCherry column, the other three contain nothing in that column (not "No" - nothing/blank).
This query works fine:
select definition from desserts
where (Toppings = 'Chocolate') and
(MaraschinoCherry <> 'Yes')
order by id
...returning the expected three records; but this one returns nothing at all, rather than the two records I expect:
select definition from desserts
where (Toppings = 'Chocolate') and
(MaraschinoCherry = 'Yes')
order by id
???
The answer to your question is simple. Any comparison to a NULL value, with two exceptions, produces NULL as the result. So,
MaraschinoCherry = 'Yes'
and
MaraschinoCherry <> 'Yes'
Both return NULL when MaraschinoCherry has a NULL value. NULL comparisons are treated the same as FALSE.
The two exceptions are: IS NULL and IS NOT NULL. Note that "= NULL" always returns NULL, which is interpreted as FALSE.
The normal way to fix this is by using COALESCE:
COALESCE(MaraschinoCherry, 'NO') = 'Yes'
(The function ISNULL() is kind of equivalent, but COALESCE allows more arguments and is standard SQL.)
There are other ways you can fix this, such as by specifying a default value for the column when you define the table, by adding an explicit comparison to NULL, by declaring the column to be "NOT NULL", or in some databases by overriding the behavior of NULLs in comparisons to violate the SQL standards (HIGHLY NOT RECOMMENDED!).