How to handle null and NULL value in sql - mysql

So I have been facing this weird situation in mysql where somehow null values are inserted in my table.
I'm talking about null value not NULL value.
I have attached image for better understating
as you can see name column have null and mobile_no have NULL
So after using this query
select Case when t1.name IS NULL then 'NA'
when t1.name= 'NA' or 'null' or NULL then 'NA'
else t1.name end as 'Name',
Case when t1.mobile_no IS NULL then 'NA'
when t1.mobile_no= 'NA' or 'null' or NULL then 'NA'
else t1.mobile_noend as 'Mobile no' from student;
after this I'm getting this result
|Name|Mobile no|
----------------
|null|NA |
but I want below result
|Name|Mobile no|
----------------
|NA |NA |

To compare a column with multiple values use col IN (x, y, z), not col = x OR y OR z.
You also can't compare with NULL using = or IN, so that has to be a separate check.
select
Case
when t1.name IS NULL OR t1.name IN ('NA' or 'null') then 'NA'
else t1.name
end as 'Name'

Can you try use IN statement? That should work.
select Case WHEN (t1.name IN ('NA', 'null') OR t1.name IS NULL) THEN 'NA' else t1.name end as 'Name',
Case WHEN (t1.mobile IN ('NA', 'null') OR t1.mobile IS NULL) THEN 'NA' else t1.mobile_no end as 'Mobile no' from student;

Related

SQL Convert a char to boolean

I have in my table one row with a char value. When the value is NULL then a false should be outputted. If the value is not NULL then a true should be outputted.
So when I try to set user_group.tUser to 0 or 1 then I'm getting this error:
Invalid column name 'false'.
Invalid column name 'true'.
SELECT COALESCE((SELECT name
FROM v_company
WHERE companyId = userView.companyId), ' ') AS company,
userView.value AS companyUser,
userView.display AS displayedUser,
CASE
WHEN user_group.tUser IS NULL THEN 0
ELSE 1
END AS userIsMemberOfGroup
FROM v_user userView
LEFT OUTER JOIN cr_user_group user_group
ON ( user_group.group = 'Administrators'
AND user_group.tUser = userView.value )
ORDER BY company ASC,
displayedUser ASC
I think this is the logic you want:
SELECT COALESCE(v.name, ' ') as company,
u.value as companyUser, u.display as displayedUser,
(EXISTS (SELECT 1
FROM cr_user_group ug
WHERE ug.group = 'Administrators' AND
ug.tUser = uv.value
)
) as userIsMemberOfGroup
FROM v_user u LEFT JOIN
v_company c
ON c.companyId = v.companyId
ORDER BY company ASC, displayedUser ASC ;
In general, MySQL is very flexible about going between booleans and numbers, with 0 for false and 1 for true.
You can use MySQL IF function to return 'false' when name IS NULL, else 'true':
SELECT IF(name IS NULL, 'false', 'true')
FROM table;
A simple CASE expression would work here:
SELECT
name,
CASE WHEN name IS NOT NULL THEN true ELSE false END AS name_out
FROM yourTable;
We could also shorten the above a bit using IF:
IF(name IS NOT NULL, true, false)
SELECT
CASE
WHEN name IS NULL THEN 'false'
ELSE 'true'
END
FROM
table1;

Sum of 2 fetched columns in other column in Big query SQL

select x,
count(case when i='abc' then 1 else null end) as ele1,
count(case when i='def' then 1 else null end) as ele2,
sum(ele1+ele2) as sum1 from (INNER QUERY)
When i am using sum(ele1+ele2), it is throwing error that ele1 not found. How to fetch sum1 in the same query without using any other outer query?
You can't use alias as column name in select
select x,
count(case when i='abc' then 1 else null end) as ele1,
count(case when i='def' then 1 else null end) as ele2,
sum( ( case when i='abc' then 1 else null end ) +
( case when i='def' then 1 else null end ) ) as sum1
from (INNER QUERY)
You cannot use alias as a column name, but if your concern is in verboseness - in your particular case you can write something like below, which is easy readable and skinny enough (for BigQuery Legacy SQL)
SELECT
SUM( i ='abc' ) AS ele1,
SUM( i = 'def' ) AS ele2,
SUM( i IN ('abc', 'def') ) AS sum1
FROM (INNER QUERY)

conditional insert into mysql

I am quite newbie with MySQL (5.1) and I don't achieve to do a conditional "insert into".
For each record, I want to insert into the same columns (1 and 2) from an empty/destination table, either 2 fields (A and B) or 2 other fields (C and D) from a source table containing several records.
Here my query:
INSERT INTO DB.table_destination(field1, field2)
SELECT
CASE
WHEN fieldAA='value1' THEN (
SELECT fieldA, fieldB
FROM DB.table_source<BR>
)
ELSE (
SELECT fieldC, fieldD
FROM DB.table_source
)
END
FROM db.table_source
Note that the fieldAA belongs to the table_source too.
I have an error around the second SELECT. Depending on some tiny changes in my script, it sometimes complains that I have more than one row.
I am stuck on that issue for a while, so I will greatly appreciate your help.
[EDIT]
Thanks a lot for your advices! It works perfectly with this simple example.
However, my study case is in the real life a bit more complex, as I have to deal with 3 source tables, including one condition (JOIN) between tables_source_1 and table_source_2, and one spatial function between table_source_1 and table_source_3.
Here my query that returns me the result from only one condition:
INSERT INTO test.OBSERVATION (CODE_INSEE,ID_SITE,LONGWGS84,LATWGS84)
SELECT
CASE METHODE_LOC WHEN '13' THEN insee_zerofill ELSE INSEE_zero END,
CASE METHODE_LOC WHEN '13' THEN '' ELSE ID_SITE END,
CASE METHODE_LOC WHEN '13' THEN GPS_TEL_LNG ELSE LONG_LIEU_DIT END,
CASE METHODE_LOC WHEN '13' THEN GPS_TEL_LAT ELSE LAT_LIEU_DIT END
FROM odk.test_insee, odk.site_clone RIGHT JOIN odk.DEMO_OISEAUX9_FULL_CORE ON odk.site_clone.ID_SITE=odk.DEMO_OISEAUX9_FULL_CORE.SITE_OBS
WHERE odk.GISWithin(GeomFromText(CONCAT('POINT(',GPS_TEL_LNG,' ',GPS_TEL_LAT,')')), SHAPE)
Tables details
1) odk.test_insee contains SHAPE (geometry used in the spatial function GISWithin) and insee_zerofill.
2) DEMO_OISEAUX9_FULL_CORE contains GPS_TEL_LNG & GPS_TEL_LAT (filled when METHODE_LOC is equal to 13), ID_SITE (filled when METHODE_LOC is different from 13).
3) odk.site_clone contains INSEE_zero, LONG_LIEU_DIT, LAT_LIEU_DIT.
I tried to set a CASE in the WHERE condition to tell it to perform the function only when ID_SITE is null, but without success so far.
Any ideas?
Thanks in advance!
[EDIT 2]
Now, it works! I should have repeated the specific condition within the CASE for EACH field to select, as followed:
SELECT
CASE METHODE_LOC WHEN '13' THEN
(SELECT insee_zerofill
FROM odk.test_insee, odk.DEMO_OISEAUX9_FULL_CORE
WHERE odk.GISWithin(GeomFromText(CONCAT('POINT(',`GPS_TEL_LNG`,' ',`GPS_TEL_LAT`,')')), SHAPE) )
ELSE
(SELECT INSEE_zero
FROM odk.site_clone RIGHT JOIN odk.DEMO_OISEAUX9_FULL_CORE
ON odk.site_clone.ID_SITE=odk.DEMO_OISEAUX9_FULL_CORE.SITE_OBS
WHERE odk.DEMO_OISEAUX9_FULL_CORE.SITE_OBS is not NULL )
END,
CASE METHODE_LOC WHEN '13' THEN ''
ELSE
(SELECT ID_SITE
FROM odk.site_clone RIGHT JOIN odk.DEMO_OISEAUX9_FULL_CORE
ON odk.site_clone.ID_SITE=odk.DEMO_OISEAUX9_FULL_CORE.SITE_OBS
WHERE odk.DEMO_OISEAUX9_FULL_CORE.SITE_OBS is not NULL )
END,
CASE METHODE_LOC WHEN '13' THEN
(SELECT GPS_TEL_LNG
FROM odk.test_insee, odk.DEMO_OISEAUX9_FULL_CORE
WHERE odk.GISWithin(GeomFromText(CONCAT('POINT(',`GPS_TEL_LNG`,' ',`GPS_TEL_LAT`,')')), SHAPE) )
ELSE
(SELECT LONG_LIEU_DIT
FROM odk.site_clone RIGHT JOIN odk.DEMO_OISEAUX9_FULL_CORE
ON odk.site_clone.ID_SITE=odk.DEMO_OISEAUX9_FULL_CORE.SITE_OBS
WHERE odk.DEMO_OISEAUX9_FULL_CORE.SITE_OBS is not NULL )
END,
CASE METHODE_LOC WHEN '13' THEN
(SELECT GPS_TEL_LAT
FROM odk.test_insee, odk.DEMO_OISEAUX9_FULL_CORE
WHERE odk.GISWithin(GeomFromText(CONCAT('POINT(',`GPS_TEL_LNG`,' ',`GPS_TEL_LAT`,')')), SHAPE) )
ELSE
(SELECT LAT_LIEU_DIT
FROM odk.site_clone RIGHT JOIN odk.DEMO_OISEAUX9_FULL_CORE
ON odk.site_clone.ID_SITE=odk.DEMO_OISEAUX9_FULL_CORE.SITE_OBS
WHERE odk.DEMO_OISEAUX9_FULL_CORE.SITE_OBS is not NULL )
END
FROM odk.DEMO_OISEAUX9_FULL_CORE ;
this wawy for case
INSERT INTO DB.table_destination(field1, field2)
SELECT CASE fieldAA WHEN 'value1' THEN fieldA ELSE fieldC END ,
CASE fieldAA WHEN 'value1' THEN fieldB ELSE fieldD END
FROM db.table_source
If i understand correctly you question and you want perform your insert select only if ID_SITE is null then you should use
INSERT INTO test.OBSERVATION (CODE_INSEE,ID_SITE,LONGWGS84,LATWGS84)
SELECT
CASE METHODE_LOC WHEN '13' THEN insee_zerofill ELSE INSEE_zero END,
CASE METHODE_LOC WHEN '13' THEN '' ELSE ID_SITE END,
CASE METHODE_LOC WHEN '13' THEN GPS_TEL_LNG ELSE LONG_LIEU_DIT END,
CASE METHODE_LOC WHEN '13' THEN GPS_TEL_LAT ELSE LAT_LIEU_DIT END
FROM odk.test_insee, odk.site_clone RIGHT JOIN odk.DEMO_OISEAUX9_FULL_CORE ON odk.site_clone.ID_SITE=odk.DEMO_OISEAUX9_FULL_CORE.SITE_OBS
WHERE odk.GISWithin(GeomFromText(CONCAT('POINT(',GPS_TEL_LNG,' ',GPS_TEL_LAT,')')), SHAPE)
AND ID_SITE is null ;
you can use both case when is null
INSERT INTO DB.table_destination(field1, field2)
SELECT CASE fieldAA WHEN is null THEN fieldA ELSE fieldC END ,
CASE fieldAA WHEN 'value1' THEN fieldB ELSE fieldD END
FROM db.table_source
or ifnull
INSERT INTO DB.table_destination(field1, field2)
SELECT ifnull( fieldAA, your_column_for_null) ,
CASE fieldAA WHEN 'value1' THEN fieldB ELSE fieldD END
FROM db.table_source

Query to Get Counts of Ids under 2 different Conditions with Case When Statement

So I Have a Table Structure like the one below.
Here are the Conditions:
I call 'Tag' as the IDs with none of Condition(x) as NULL.
I call 'UnTag' as the IDs with any of the Condition(x) is NULL.
I want to Classify 'Classification1' in the below Format:
I want the output in the following structure:
I wrote a code but somehow it is not giving me the desired result.
I Used Case when to Classify the Classification1 and then ran a sub-query for taking out Count.
Please help if there is a different Approach and how to incorporate the Case when in Group by statement.
I wrote this query:
SELECT
CASE
WHEN UPPER(CM1.Classification1) IN ('A', 'C','G') THEN 'X'
WHEN UPPER(CM1.Classification1) IN ('B', 'F') THEN 'Y'
WHEN UPPER(CM1.Classification1) IN ('D', 'E') THEN 'Z'
ELSE 'Undefined' END AS New_Classification,
(SELECT
COUNT(CASE
WHEN UPPER(CM2.Classification1) IN ('A', 'C','G') THEN 'X'
WHEN UPPER(CM2.Classification1) IN ('B', 'F') THEN 'Y'
WHEN UPPER(CM2.Classification1) IN ('D', 'E') THEN 'Z'
ELSE 'Undefined' END)
FROM TABLE1 CM2 WHERE
CM2.Condition1 IS NOT NULL AND
CM2.Condition2 IS NOT NULL AND
CM2.Condition3 IS NOT NULL AND
CM2.Condition4 IS NOT NULL AND
CM1.ID=CM2.ID) AS Count_of_tagged,
(SELECT
COUNT(CASE
WHEN UPPER(CM3.Classification1) IN ('A', 'C','G') THEN 'X'
WHEN UPPER(CM3.Classification1) IN ('B', 'F') THEN 'Y'
WHEN UPPER(CM3.Classification1) IN ('D', 'E') THEN 'Z'
ELSE 'Undefined' END)
FROM TABLE1 CM3 WHERE
(CM3.Condition1 IS NULL OR
CM3.Condition2 IS NULL OR
CM3.Condition3 IS NULL OR
CM3.Condition4 IS NULL) AND
CM1.ID=CM2.ID) AS Count_of_untagged
FROM TABLE1 CM1
You shouldn't need a subquery, as a starting point I came up with:
SELECT CASE Classification1
WHEN 'A' THEN 'X'
WHEN 'B' THEN 'Y'
WHEN 'C' THEN 'X'
WHEN 'D' THEN 'Z'
WHEN 'E' THEN 'Z'
WHEN 'F' THEN 'Y'
WHEN 'G' THEN 'X'
END new_classification,
SUM(
Condition1 IS NOT NULL AND
Condition2 IS NOT NULL AND
Condition3 IS NOT NULL AND
Condition4 IS NOT NULL /* 1 for true, 0 for false */
) tagged_count,
SUM(
Condition1 IS NULL OR
Condition2 IS NULL OR
Condition3 IS NULL OR
Condition4 IS NULL
) untagged_count,
FROM table_name
GROUP BY new_classification
Can give a try at the following sql and tell me if this is what you need
select
CASE
WHEN classification ='A' THEN 'X'
WHEN classification ='B' THEN 'Y'
WHEN classification ='C' THEN 'X'
WHEN classification ='D' THEN 'Z'
WHEN classification ='E' THEN 'Z'
WHEN classification ='F' THEN 'Y'
WHEN classification ='G' THEN 'X'
END as classification,
sum(case when condition1 is not null and condition2 is not null and condition3 is not null and condition4 is not null then 1 else 0 end) as tagged
sum(case when condition1 is null or condition2 is null or condition3 is null or condition4 is null then 1 else 0 end) as untagged
from table
GROUP BY CASE
WHEN classification ='A' THEN 'X'
WHEN classification ='B' THEN 'Y'
WHEN classification ='C' THEN 'X'
WHEN classification ='D' THEN 'Z'
WHEN classification ='E' THEN 'Z'
WHEN classification ='F' THEN 'Y'
WHEN classification ='G' THEN 'X'
END ;

MySql, Postgres, Oracle and SQLServer ignoring IS NOT NULL filter

While I was preparing an answer to one of our fellows here on SO I've encounter an odd situation, at least to me. The original question is here: Pivot Table Omitting Rows that Have Null values
I've modified the query to use max instead of group_concat in order to show the "problem" in all databases.
SELECT
id,
max(case when colID = 1 then value else '' end) AS fn,
max(case when colID = 2 then value else '' end) AS ln,
max(case when colID = 3 then value else '' end) AS jt
FROM tbl
GROUP BY id
The result of this query is this:
ID FN LN JT
1 Sampo Kallinen Office Manager
2 Jakko Salovaara Vice President
3 (null) Foo No First Name
The user asks to filter the row with id 3 because the field value is null.
When it seems pretty obvious that only it needs to do was to add a WHERE value IS NOT NULL constraint on that query to achieve what the user expect. It won't work.
So I start to test it on the other databases to see what happens (Queries with the WHERE CLAUSE)
SELECT
id,
max(case when colID = 1 then value else '' end) AS fn,
max(case when colID = 2 then value else '' end) AS ln,
max(case when colID = 3 then value else '' end) AS jt
FROM tbl
WHERE value is not null
GROUP BY id
Mysql: http://sqlfiddle.com/#!2/78395/1
Postgres: http://sqlfiddle.com/#!15/78395/1
SQLServer: http://sqlfiddle.com/#!6/78395/1
Oracle: http://sqlfiddle.com/#!4/78395/1
For my surprise the result was the same, none worked.
Then I tried a different version of the same query:
SELECT * FROM (
SELECT
id,
max(case when colID = 1 then value else '' end) AS fn,
max(case when colID = 2 then value else '' end) AS ln,
max(case when colID = 3 then value else '' end) AS jt
FROM tbl
GROUP BY id
) T
WHERE fn IS NOT NULL
AND ln IS NOT NULL
AND jt IS NOT NULL
Oracle: http://sqlfiddle.com/#!4/78395/2 WORKED
MySql: http://sqlfiddle.com/#!2/78395/2
Postgres: http://sqlfiddle.com/#!15/78395/2
SQLServer: http://sqlfiddle.com/#!6/78395/2
The only way I could make it work on all databases was with this query:
SELECT
id,
max(case when colID = 1 then value else '' end) AS fn,
max(case when colID = 2 then value else '' end) AS ln,
max(case when colID = 3 then value else '' end) AS jt
FROM tbl
WHERE NOT EXISTS (SELECT * FROM tbl b WHERE tbl.id=b.id AND value IS NULL)
GROUP BY id
So I ask:
What is happening here that except for that specific case on Oracle all other DBs seem to ignore the IS NOT NULL filter?
To omit the row from the result if any of the source rows for the same id has value IS NULL, a solution in Postgres would be to use the aggregate function every() or (synonym for historical reasons) bool_and() in the HAVING clause:
SELECT id
, max(case when colID = 1 then value else '' end) AS fn
, max(case when colID = 2 then value else '' end) AS ln
, max(case when colID = 3 then value else '' end) AS jt
FROM tbl
GROUP BY id
HAVING every(value IS NOT NULL);
SQL Fiddle.
Explain
Your attempt with a WHERE clause would just eliminate one source row for id = 3 in your example (the one with colID = 1), leaving two more for the same id. So we still get a row for id = 3 in the result after aggregating.
But since we have no row with colID = 1, we get an empty string (note: not a NULL value!) for fn in the result for id = 3.
A faster solution in Postgres would be to use crosstab(). Details:
PostgreSQL Crosstab Query
Other RDBMS
While EVERY is defined in the SQL:2008 standard, many RDBMS do not support it, presumably because some of them have shady implementations of the boolean type. (Not dropping any names like "MySQL" or "Oracle" ...). You can probably substitute everywhere (including Postgres) with:
SELECT id
, max(case when colID = 1 then value else '' end) AS fn
, max(case when colID = 2 then value else '' end) AS ln
, max(case when colID = 3 then value else '' end) AS jt
FROM tbl
GROUP BY id
HAVING count(*) = count(value);
Because count() doesn't count NULL values. In MySQL there is also bit_and().
More under this related question:
Is there any equivalent to Postgresql EVERY aggregate function on other RDBMS?
It works in Oracle because Oracle handles NULL incorrectly in that NULL and '' are the same. The other databases don't do this because it is wrong. NULL is unknown, versus '' which is just a blank, empty string.
So if your where clause said something like WHERE (fn IS NOT NULL or fn <> '') you would probably get further.
I think this is a case where a HAVING clause will do what you need.
SELECT id, max ... (same stuff as before)
FROM tbl
GROUP by id
HAVING fn IS NOT NULL
AND ln IS NOT NULL
AND jt IS NOT NULL