I am getting an inconsistent result from below two SQL queries.
Query1 : select (case when 'Abc' = null then 1 else 0 end) from dual
Query2 : select (case when ('Abc' <> null) then 1 else 0 end) from dual
Result for both queries same i.e
0
What's wrong am I missing some thing ?
NOTE : : I know I can use IS NULL and IS NOT NULL but my question is why result from above queries is inconsistent.
EDIT : Added from answer of #ppeterka.
select (case when null = null then 1 else 0 end) from dual
This returns 0 too. Null is not even equal to itself.
But then what does this return?
select (case when null <> null then 1 else 0 end) from dual
0 again
SQLFiddle link
Because NULL is unknown that is why the result is 0. When you want to compare a column or a value if it is null or not, use IS NULL or IS NOT NULL.
select (case when 'Abc' IS null then 1 else 0 end) from dual -- 0
select (case when ('Abc' IS NOT null) then 1 else 0 end) from dual -- 1
SQLFiddle Demo
The result of comparing anything to NULL, even itself, is always NULL(not TRUE or FALSE).
Searched CASE expression:
If no Boolean_expression evaluates to TRUE, the Database Engine returns the else_result_expression if an ELSE clause is specified, or a NULL value if no ELSE clause is specified.
In your case the result always will be 0, because 0 in ELSE clause
To add a bit of twist to this, try this out:
select (case when null = null then 1 else 0 end) from dual
This returns 0 too. Null is not even equal to itself.
But then what does this return?
select (case when null <> null then 1 else 0 end) from dual
This returns 0 again! Oh holy... It is not even not equal to itself, while it is not equal to itself... Quite a situation to grasp without getting insane...
Why to keep this all in mind? - one might ask
One example is indexing: in Oracle, indexes don't work the way one would expect them to work on NULL values where a column permits the use of that value. This means that given an index, if all the values (fields, functions on fields, etc) of a row that are included in the index are all NULL, that row won't be indexed in that given index. So this means that an index, that has only one value indexed (for example, a field directly), a null value would mean that row not to be included in the index.
To overcome this
it might be advisable to add an index with a distinct, exact value semantically representing the NULL meaning, like NVL(mynullcol,-1) on a column only containing positive integers to be able to query them quickly.
or you could add a constant value to form a "semi-multivalue" index, that indexes all rows, where one can be null, as the other is a constant. (create index idx_myindex on table(column_with_nulls,1); )
(This question and this article detail this subject in a bit more depth)
Another example is ordering...
select (case when null < null then 1 else 0 end) from dual;
select (case when null > null then 1 else 0 end) from dual;
Both 0. This is OK... We expected this by now... And what about this?
select (case when 'Abc' > null then 1 else 0 end) from dual;
select (case when null > 'Abc' then 1 else 0 end) from dual;
Uh-oh... Both 0 again. This might be an issue - how is ordering going to work?
select col_1 from
(select null as col_1 from dual)
union all (select 'Abc' as col_1 from dual)
union all (select null as col_1 from dual)
union all (select null as col_1 from dual)
order by col_1
This however consistently returns:
Abc
null
null
null
Using ... order by col_1 DESC returns:
null
null
null
Abc
So from this, on an empirical basis, it does seem that 'Abc' < null... However, as per the valuable comment of #ypercube:
the sort order can be set with the NULLS LAST and NULLS FIRST modifiers (at least in Oracle).
What you observe is the default sort order when the ORDER BY has no modifier
NULL is a twisted business, it is wise to steer away from it if it is possible... (And this is not only true for SQL, but for certain situations in OOP languages too.)
You can't use <> or = with nulls. You need to say
select (case when 'Abc' is null then 1 else 0 end) from dual
and
select (case when 'Abc' is not null then 1 else 0 ) from dual
It is not inconsistent.
if you have 2 objects A,B then it's one of the following three:
A equals B
A not equals B
you cannot compare A and B
It's like examining if (0/0 > 0) or (0/0 < 0) or (0/0 = 0). You just cannot compare them. every option is false
For your example: case checks if your argument is true
argument ('abc'=null) is not true, it's null
argument ('abc'<>null) is not true, it's null
The value NULL means the data value for the column is Unknown. A NULL is not synonymous with Zero, or zero length string or blank.
Anything you compare with NULL will result in Unknown (NULL).
Please check this to clear your doubts. To have the correct result, use IS NULL or IS Not NULL as you already know.
Related
I have a table where a column is mostly NULL except for one row.
ID STATUS VALUE POS
1 'BAD' 200 0
2 NULL 200 0
3 NULL 300 1
4 'OK' 0 2
if I do
Select * from table where STATUS != 'OK'
I expect
ID STATUS VALUE POS
1 'BAD' 200 0
2 NULL 200 0
3 NULL 300 1
But I get
ID STATUS VALUE POS
1 'BAD' 200 0
I want to know why, I know I can do something else like Where ID = 4, but why the query above returns an empty result for NULL values?
Thanks
Comparing with NULL is always NULL. Think about NULL like it is "unknown value". Does some unknown value is not equal to 'OK'? this is unknown... so the result is NULL.
In logical expressions NULL is treated as FALSE. So you do not receive the rows which you want to receive.
You must either apply additional check for NULL value (WHERE status != 'OK' OR status IS NULL) or convert NULL value to some definite constant value before compare (WHERE COALESCE(status, '') != 'OK').
Pay attention - this interpretation differs from one used in CHECK constraint (including FOREIGN KEY constraint) in which NULL value is treated as "matched".
It isn't possible to use "equal" or "not equal" for NULL values
You MUST use IS NULL or IS NOT NULL e.g:
Select * from table where STATUS != 'OK' OR Status IS NULL
I have a sql query as follow:
but the problem is that if the the second select staement with dataitem=3 returns null then the whole calculation becomes 0. For example for first select I have 100 and for second it returns null. Adding them should result 100 but it gives back 0!!!!!
can anyone say the reason and also what to do to get rid of that?
Here is also copiable code:
select( (
SELECT sum(Sentiment)
FROM entity_epoch_data
WHERE EpochID IN
(SELECT ID
FROM epoch
WHERE StartDateTime>='2013-11-1'
AND EndDateTime<='2013-11-30')
AND EntityID =86
AND DataitemType=0
)+
(SELECT sum(Sentiment)
FROM entity_epoch_data
WHERE EpochID IN
(SELECT ID
FROM epoch
WHERE StartDateTime>='2013-11-1'
AND EndDateTime<='2013-11-30')
AND EntityID =86
AND DataitemType=3)
)
Just add to the SQLs that represent values the IFNULL command like IFNULL((select sum()......), 0) it should work fine.
But a little peace of advice. You should improve that query.
I beleave that this query you do the same thing.
SELECT sum(entity_epoch_data.Sentiment)
FROM entity_epoch_data INNER JOIN epoch
ON entity_epoch_data.EpochID = epoch.id
WHERE epoch.StartDateTime>='2013-11-1'
and epoch.EndDateTime<='2013-11-30'
AND entity_epoch_data.EntityID =86
and entity_epoch_data.DataitemType in (0,3)
You are summing the sums of the DataitemType 3 and 0 it just can be one query with a join
Use CASE statements instead of the statements you're using.
select sum(case when StartDateTime>='2013-11-1' and EndDateTime<='2013-11-30' and DataitemType=0 then Sentiment else 0 end) as Sentiment_0, sum(case when StartDateTime>='2013-11-1' and EndDateTime<='2013-11-30' and DataitemType=3 then Sentiment else 0 end) as Sentiment3 from (tables_joined) where EntityID =86
Adding null is undefined and therefore returns null or 0. You can use a CASE expression to avoid that problem.
SELECT SUM(CASE null = sentiment THEN 0 ELSE sentiment END) FROM ....
If your DB does not support CASE inside the SUM() function create a VIEW that uses CASE to substitute the null values with 0.
I have simple table (test) where I need to perform some additions (I want to get a row total and a column total).
id var1 var2
1 NULL NULL
2 10 NULL
For column totals, summing works as expected (NULL is ignored in the addition):
SELECT SUM(var1) FROM test
10
For row totals, addition does not ignore NULL (if any column is NULL the result is NULL):
SELECT var1+var2 FROM test
NULL
NULL
What I want it to return is:
SELECT var1+var2 FROM test
NULL
10
Is there a way to get MySQL to treat NULL as 0 in an addition?
You want to use coalesce():
select coalesce(var1, 0) + coalesce(var2, 0)
coalesce() is ANSI standard and available in most databases (including MySQL).
use the IFNULL function
SELECT IFNULL(var1, 0) + IFNULL(var2, 0) FROM test
select
Case when (coalesce(`var1`, 0) + coalesce(`var2`, 0))=0
then NULL
else coalesce(`var1`, 0) + coalesce(`var2`, 0)
end
from test
SQL FIDDLE
Well, the values aren't null per say, they are in VARCHAR(30) but in decimal form. However some of the records have "NA" in some fields. I would like mysql to skip those rows in SUM calculation when "NA" is present in the fields used for the SUM. Mysql is treating all incalculable fields as 0. The 0 from fields containing "NA" is misleading. I am doing a GROUP BY TABLE.ID.
Edit:
SELECT
SUM(
CASE
WHEN X >1 THEN 1
WHEN X<-1 THEN 2
ELSE 3
END
CASE
WHEN Y >1 THEN 1
WHEN Y <-1 THEN 2
ELSE 3
END)
AS "Col X+Y";
FROM TableA
GROUP BY TableA_ID;
Sometimes X and/or Y = "NA" on certain fields. I get 6 if both X and Y on TableA_ID = 17 or other numbers when one of them is "NA".
Edit (quoting my comment on VARCHAR):
"I tried storing my values as DEC(5,2), but some of the data from Excel have NA's in the fields. I did set X DEC(5,2) NULL and tried inserting NA into it but kept getting an error (cannot be null). I also tried making the default value "NA" but still get an error (cannot be null). I'll add in a sample query as edit."
I got it. I added in another WHERE clause using
WHERE ..... AND(Colx IS NOT NULL OR Coly IS NOT NULL OR ......);
I switched back the values to DEC(3,1) and made the fields NULLable with defaults null if the field value is NULL. I had to understand how to use NULL. I took out the 'NA's in Excel and left those field values blank.
if foo1 is null or NA just sum it as zero (the neutrum value in the addition), otherwise sum the value.
select sum( case when foo1 is null or foo1 = 'NA' then 0 else foo1 end) as sum, foo2
from FooTable group by foo2
or
select sum(foo1) from FooTable
where (foo2 <> 'NA' and foo2 is null) and (foo3 <> 'NA' or foo3 is null )
group by foo4
Bit of a newbie and probably a very basic question to you, but is driving me mad.
I have a mysql table. I have a record which has a record id, and six other fields which contain names of photographs.
So,
Record_id, photo1, photo2, photo3, photo4, photo5, photo6
I want have have the end result where I have a column called 'TOTAL' which shows the number of how many records have photographs in them as a TOTAL. So, Record 1 may have a total of 5 photographs, record 2 may have 3 photographs, and record 3 may have a total of NO records for that record etc?
Now some of the photographs names which are uploaded to the field may contain numbers, ie, photo244.jpg, or pic3993.jpg etc - so I don't want these numbers added together, I am just looking for whether the field has a name in it etc, and this would be counted as 1 to add to the total. So the end result in on the page is that record 13 (for example) has a total of 4 photographs etc - sorry if not a good explanation!
It may have something to do with SUM or COUNT, but have spent ages trying to get combination or correct key/syntax! Can anyone help please by giving an example of the mysql select statement - would be grateful!
I presume that if there is no photo, then the field photoX is null or is empty.
So use CASE for output 0 if the field is null or empty, 1 else.
SELECT Record_id
,
CASE WHEN (photo1 IS NULL OR photo1 = '') THEN 0 ELSE 1 END
+ CASE WHEN (photo2 IS NULL OR photo2 = '') THEN 0 ELSE 1 END
+ CASE WHEN (photo3 IS NULL OR photo3 = '') THEN 0 ELSE 1 END
+ CASE WHEN (photo4 IS NULL OR photo4 = '') THEN 0 ELSE 1 END
+ CASE WHEN (photo5 IS NULL OR photo5 = '') THEN 0 ELSE 1 END
+ CASE WHEN (photo6 IS NULL OR photo6 = '') THEN 0 ELSE 1 END
AS Total
FROM myTable
It will the best query:
SELECT
Record_id,
(6 - IFNULL(photo1,1) - IFNULL(photo2,1) - IFNULL(photo3,1) - IFNULL(photo4,1) - IFNULL(photo5,1) - IFNULL(photo6,1)) AS TOTAL
FROM
table
Something like this will give you a count by Photo1, Photo2, etc.:
SELECT
SUM(CASE WHEN photo1 IS NOT NULL THEN 1 END) AS Photo1Count,
SUM(CASE WHEN photo2 IS NOT NULL THEN 1 END) AS Photo2Count,
SUM(CASE WHEN photo3 IS NOT NULL THEN 1 END) AS Photo3Count,
SUM(CASE WHEN photo4 IS NOT NULL THEN 1 END) AS Photo4Count,
SUM(CASE WHEN photo5 IS NOT NULL THEN 1 END) AS Photo5Count
FROM MyTable
Something like this will count how many rows have at least one photograph:
SELECT SUM (
CASE WHEN
photo1 IS NOT NULL OR
photo2 IS NOT NULL OR
photo3 IS NOT NULL OR
photo4 IS NOT NULL OR
photo5 IS NOT NULL THEN 1 END)
FROM MyTable
Note that these queries are for grand totals. They don't show activity by row. If activity by row is needed, try the answers from Scorpi0 or Michael Sivolobov.