I have a table like the one above with the two left columns (Both of them are integer) and I added to this table two more fields:
Table1:
Asset_Value Contract_Value
-------------------------------
0 NULL
NULL 200
0 NULL
And the query:
Select
Asset_Value, Contract_Value,
Case
when Asset_Value is null
then 1
else 0
end As Ind_ForNullA,
Case
when Contract_Value is null
then 1
else 0
end As IndForNullC
from
table1
However, I get strange results:
Asset_Value Contract_Value Ind_ForNullA IndForNullC
----------------------------------------------------
0 NULL 1 1
NULL 200 0 0
0 NULL 0 1
Update : Never Mind. Damm comma has been forgetten.
Try with ' ' empty string instead of null.
Try to use the function ASCII
ASCII ( character_expression )
Using this function you can understand what is the really character in the column Asset_Value: for example NULL value must have ASCII code: '00' Table with character ASCII code
Why are you bothering to define something as NULL--which is appropriate--but, in this case or that one, changing it to one or zero (an attempt at Boolean, I imagine)--which is inappropriate?
What will you do next: decide that, in a third report, you want to have a REAL boolean that displays TRUE or FALSE?
Go with NULL consistently, throughout the entire application, everywhere, or don't. However, DO NOT MIX AND MATCH PARADIGMS and expect consistent results. Also, try not to rely upon CASE: there's very, very legitimate reason to depend upon that--especially for something as simplistic as what you're doing.
FYI, the only reason I can conceive why you would want this "indicator" field is so that you can test whether INDICATOR_A = 1. However, since you can test ASSET IS NULL, why even bother? NEVER introduce extraneous mechanisms when there is no overpowering reason to do so.
Related
I have a TERADATA dataset that resembles the below:
Customer_ID | Targeting_Region
12 | targ=EU, targ=!Eu.Fr
34 | targ=Asia
56 | targ=!EU
The '!' denotes 'does not equal'. For example, the customer in Row #1 wants to target the EU, but exclude France.
I want to create a field that flags (with a '1') any row where there is 'positive' targeting. By 'positive' targeting I am referring to any row where a specific region as been explicitly INCLUDED ('negative' targeting would be where a region is explicity EXCLUDED, such as the exclusion of France in Row #1). For example, Row #1 contains both positive and negative targeting, Row #2 contains only positive targeting, Row #3 contains only negative targeting.
The problem I am encountering is that a simple case statement won't work (as far as I can tell). I have tried the 2 statements below:
(case when targeting_region like '%targ=%'; then 1 else 0 end) as target_flag
(case when ((targeting_region like '%targ=%';) and (targeting_region not like '%targ=!%';)) then 1 else 0 end) as target_flag
The 1st statement above doesn't work because it will return 1 for both 'targ=' and 'targ=!
The 2nd statement above doesn't work because it will return 1 for rows that ONLY have positive targeting. As such, Row #1 (above) would return a 0 (I want it to return a 1)
Note that that value following 'targ=' could also be a number. E.g., 'targ=12345'
Any ideas on how I could accomplish this? I have heard that teradata has something called regexp but I have been unable to find a good explanation of it after quite a bit of searching.
Thanks!
Maybe not exactly what you're looking for, but if you want a 1 only when there is a positive target and no negative target, then why not make it 0 if there exists a negative target and 1 otherwise?
For example,
case when targeting_region like '%targ=!%' then 0
when targeting_region like '%targ=%' then 1
else null -- Optional if you want to handle when no targeting regions exist
end as target_flag
Would something like this work?
(case when REGEXP_INSTR(targeting_region,'targ=[A-Z,a-z]') = 0; then 0 else 1)
I found syntax and example of REGEXP_INSTR() at
http://www.info.teradata.com/HTMLPubs/DB_TTU_14_00/index.html#page/SQL_Reference/B035_1145_111A/Regular_Expr_Functions.085.03.html#ww14955402
Because there was too little info at this site, you will have to fiddle with it to get it to work.
For example...
The equal sign in "...targ=...", and maybe even the left and right brackets, may need to be escaped, perhaps with backslash. Also, the above assumes that if there is no match, the function returns 0 (rather than NULL). It may need to be changed from "=0" to "IS NULL". Also, I assume that the parameters after the first two are optional. You may need to specify them, e.g., "1,1,i". Also, the expression could be simplified a bit, for example by using a shortcut for [A-Z,a-z], if you can find better documentation.
Explanation:
The second parameter specifies a "pattern" to look for in the first parameter.
1. "targ=" looks for exactly those characters.
2. "[A-Z,a-z]" looks for an alphabetic character. If a "!" occurs, it will not match and the search will proceed with the rest of the string.
3. REGEXP_SUBSTR() returns the character position where the pattern was found in the string. That's overkill because you only want to know yes it was found or no it was not, but hopefully it works because I couldn't find a simpler function.
If I understood you correctly you want 1 if there's any included target regardless of additional excluded regions?
This searches for 'targ=' followed by any other character than '!':
CASE WHEN REGEXP_INSTR(Targeting_Region,'targ=[^!]') = 0 THEN 0 ELSE 1 END
If your release doesn't include REGEXP function there might be OREPLACE:
CASE WHEN POSITION('targ=' IN OREPLACE (Targeting_Region, 'targ=!', '')) > 0 THEN 1 ELSE 0 END
The issue is i have 3 conditions good bad ugly. My goal is if one of the following condition is null then replace null to 0 else if all the conditions are null then show it as null
case when 'Good' is not null or 'Bad' is not null or 'Ugly' is not null
then coalesce(value,0)
else value
end result
The problem here is even with the condition it turns all the nulls to 0 which is not what i want. Thanks in advance
Your current expression says (in pseudocode):
IF <something is true>
IF value IS NULL
RETURN 0
ELSE
RETURN value
ENDIF
ELSE
RETURN value
ENDIF
Is that what you wanted?
I think maybe you want something like this. If I get more details I will update.
If I were just going off of this comment
the question is if good is null and bad and ugly for the same product
has a value 0-100 then i want the null to be replaced to 0. if all the
three are null for the same prod then i want them to be nulls and not
0
I would give you something like this
case
when good is not null then good
when good is null and coalesce(bad,-1) between (0 and 100) and coalesce( ugly,-1) between (0 and 100) then 0
else null
end
If you were trying to provide all 3 columns (I am assuming you have multiple columns) you might do something like this.
select
case
when good is null and bad is null and ugly is null then null
when good is null and (bad is not null or ugly is not null) then 0
else good
end as 'good column values'
,
case
when good is null and bad is null and ugly is null then null
when bad is null and (good is not null or ugly is not null) then 0
else bad
end as 'bad column values'
,
case
when good is null and bad is null and ugly is null then null
when ugly is null and (good is not null or bad is not null) then 0
else ugly
end as 'ugly column values'
Your code says "if one of good, bad, or ugly is not null" but your question says "if one of good, bad, or ugly is null"
If I'm understanding you correctly, just take out the nots.
Edit: I'm also assuming that you don't actually mean to use the literal strings "Good", "Bad" and "Ugly", but that they are meant to represent column names or something.
You should be aware that using these strings means that your code will never enter the "else" condition, as "Good", "Bad" and "Ugly" are not null.
EDIT 2: take your column names (good, bad, ugly) out of quotes so they will actually be evaluated. This is why you're still seeing that error.
In NAME table FIRST column is having null but no rows are selected. Please help me to understand.
SELECT * FROM NAME WHERE FIRST != '1'
Any comparison with null is false - = and <>, >, <, and so on. You cannot use null in an IN list as well - it would be ignored. Moreover, two nulls are not even equal to each other.
To get the nulls, you need to ask for them explicitly, like this:
SELECT * FROM NAME WHERE FIRST IS NULL OR FIRST != '1'
Any comparison to NULL returns NULL, which is equivalent to FALSE. This is true eve of not-equals.
If you want to include NULL values, do one of the following:
where first <> '1' or first is null
or
where coalesce(first, '<null>') <> '1'
In Oracle, null is not considered a legal value to select unless you explicitly ask for it:
select * from name where (first != '1') or first is null
You could also use NVL (similar to coalesce):
select * from name where nvl(first,'0') != '1'
That is correct because NULL can never be compared with anything else....
The only option that you have is to include a NULL check as an or in the command
SELECT * FROM NAME WHERE FIRST!=1 OR FIRST IS NULL
According to Oracle Documentation NULL is defined as a value not knownm or when the value is not meaningful. That is solely the reason why Oracle mentions not consider a value of ZERO as NULL. This is just an FYI, an addon. Thanks!
NULL is dumb. Period.
NULL is evil.
If X is NULL and Y is NULL, then X does in fact equal Y because they are both NULL.
It's also a PITA that I can't say
IF X IN ('a','B','C', null)
Because this condition happens. But now I have to say
IF ( X IN ('a','B','C') or X is NULL )
which is a waste of time and a risk of error if I forget the parentheses.
What irks me further is that NULL shouldn't happen in the first place. Fields (er... ok kids, I'll call them Columns) should always be initialized. Period. Stop the nulls. Don't allow them. Default values should always be zeroes or blanks so that those folks that are too lazy to initialize columns in their software will have them initialized for them automatically.
There are many instances where a failure to define default values of zeroes and blanks makes life more difficult than it has to be.
Given:
The following Select statement:
select case NULL
when NULL then 0
else 1
end
Problem:
I'm expecting this to return 0 but instead it returns 1. What gives?
Generally speaking, NULL is not something you should attempt to compare for equality, which is what a case statement does. You can use "Is NULL" to test for it. There is no expectation that NULL != NULL or that NULL = NULL. It's an indeterminate, undefined value, not a hard constant.
-- To encompass questions in the comments --
If you need to retrieve a value when you may encounter a NULL column, try this instead:
Case
When SomeColumn IS NULL
Then 0
Else 1
End
I believe that should work. As far as your original post is concerned:
Select Case NULL
When NULL then 0 // Checks for NULL = NULL
else 1 // NULL = NULL is not true (technically, undefined), else happens
end
The trouble is that your Case select automatically attempts to use equality operations. That simply doesn't work with NULL.
I was going to add this as a comment to Aaron's answer, but it was getting too long, so I'll add it as another (part of the) answer.
The CASE statement actually has two distinct modes, simple and searched.
From BOL:
The CASE expression has two formats:
The simple CASE expression compares an expression to a set of simple expressions to determine the result.
The searched CASE expression evaluates a set of Boolean expressions to determine the result.
When the simple CASE (your example) does what it describes as comparison it does an equality comparison - i.e. =
This is clarified in the later documentation:
The simple CASE expression operates by comparing the first expression
to the expression in each WHEN clause for equivalency. If these
expressions are equivalent, the expression in the THEN clause will be
returned.
Allows only an equality check.
Because anything = NULL is always false in ANSI SQL (and if you didn't know this, you need to read up on NULLs in SQL more generally, particularly also with the behavior in the other searched comparison - WHERE x IN (a, b, c)), you cannot use NULL in a simple case and have it ever be compared to a value, with a NULL either in the initial expression or in the list of expressions to be compared against.
If you want to check for NULL, you will have to use an IF/ELSE construct or the searched CASE with a full expression.
I agree that it's kind of unfortunate there is no version which supports an IS comparison to make it easier to write:
select case colname
when IS NULL then 0
else 1
end
Which would make writing certain long CASE statements easier:
select case colname
when IS NULL then ''
when 1 then 'a'
when 2 then 'b'
when 3 then 'c'
when 4 then 'd'
else 'z'
end
But that's just wishful thinking...
An option is to use ISNULL or COALESCE:
select case COALESCE(colname, 999999) -- 999999 is some value never used
when 999999 then ''
when 1 then 'a'
when 2 then 'b'
when 3 then 'c'
when 4 then 'd'
else 'z'
end
But it isn't always a great option.
In addition to the other answers, you need to change the syntax for CASE slightly to do this:
SELECT CASE
WHEN NULL IS NULL THEN 0
ELSE 1
END;
Using the value in your syntax implicitly uses an equals comparison. NULL is unknown, and so is NULL = NULL, so with your current code you will always get zero 1 (geez I did it too).
To get the behavior you want, you can use SET ANSI_NULLS ON; however note that this can change other code in ways you may not be able to predict, and the setting is deprecated - so it will stop working at all in a future version of SQL Server (see this SQL Server 2008 doc).
You need to use the IS NULL operator. Standard comparison operators do not work with NULL.
Check out these MSDN articles about Null that may be useful:
IS [NOT] NULL (Transact-SQL)
Null Values
I'm attempting to create a T-SQL case statement to filter a query based on whether a field is NULL or if it contains a value. It would be simple if you could assign NULL or NOT NULL as the result of a case but that doesn't appear possible.
Here's the psuedocode:
WHERE DateColumn = CASE #BitInput
WHEN 0 THEN (all null dates)
WHEN 1 THEN (any non-null date)
WHEN NULL THEN (return all rows)
From my understanding, the WHEN 0 condition can be achieved by not providing a WHEN condition at all (to return a NULL value).
The WHEN 1 condition seems like it could use a wildcard character but I'm getting an error regarding type conversion. Assigning the column to itself fixes this.
I have no idea what to do for the WHEN NULL condition. My internal logic seems to think assigning the column to itself should solve this but it does not as stated above.
I have recreated this using dynamic SQL but for various reasons I'd prefer to have it created in the native code.
I'd appreciate any input. Thanks.
The CASE expression (as OMG Ponies said) is mixing and matching datatypes (as you spotted), in addition you can not compare to NULL using = or WHEN.
WHERE
(#BitInput = 0 AND DateColumn IS NULL)
OR
(#BitInput = 1 AND DateColumn IS NOT NULL)
OR
#BitInput IS NULL
You could probably write it using CASE but what you want is an OR really.
You can also use IF..ELSE or UNION ALL to separate the 3 cases