Count no of column having null and non null value - mysql

Hi I have query in which i want to sum of null(0,'', NULL) and non null values in a single row.
Example: I have a table having 5 column. It contain atleast one record. In its first row 2 columns are blank and 3 columns are having some value. I want a query which will give me a result like non_null_count=3, null_count=2

Count of NOT NULL data-
SELECT Count(*)
FROM employee
WHERE salary IS NOT NULL
AND emp_name IS NOT NULL
AND manager_id IS NOT NULL
Count of NULL data-
SELECT Count(*)
FROM employee
WHERE salary IS NULL
AND emp_name IS NULL
AND manager_id IS NULL

You can use this.
SELECT ( IF(col1 IS NOT NULL, 1, 0)
+ IF(col2 IS NOT NULL, 1, 0)
+ IF(col3 IS NOT NULL, 1, 0) +... ) AS total_not_null,
( IF(col1 IS NULL, 1, 0)
+ IF(col2 IS NULL, 1, 0)
+ IF(col3 IS NULL, 1, 0) +... ) AS total_null
FROM mytable

In MySQL, boolean expressions can be treated as numbers, with "1" for true and "0" for false.
So, this does what you want:
select ((col1 is not null) + (col2 is not null) + (col3 is not null) +
(col4 is not null) + (col5 is not null)
) as num_not_null,
((col1 is null) + (col2 is null) + (col3 is null) +
(col4 is null) + (col5 is null)
) as num_null
from t;
Note that this interprets "blank" as being NULL. You can just as easily use <> '' or similar logic if "blank" means something else.
EDIT:
For other values, you need to extend the logic. A simple way is:
select ((col1 is not null and col1 not in ('0', '')) +
(col2 is not null and col2 not in ('0', '')) +
(col3 is not null and col3 not in ('0', '')) +
(col4 is not null and col4 not in ('0', '')) +
(col5 is not null and col5 not in ('0', ''))
) as num_not_null,
((col1 is null or col1 in ('0', '')) +
(col2 is null or col2 in ('0', '')) +
(col3 is null or col3 in ('0', '')) +
(col4 is null or col4 in ('0', '')) +
(col5 is null or col5 in ('0', ''))
) as num_null
from t;

Related

How to parse a string and get the value after "=" character

So I have string that should contains "Object.Name" once in a row , if I see it ,I have to get the value after "=" character. If doesn't match it anywhere in the string i should move hardcoded value.
Here is example of the string:
Object.Name=ASDD||Product.Name=DSA
Product.Name=QWE||Object.Name=WSXS
Storage.Name=12345||Object.Name=WERR||Product.Name=QAZ
I know that I should use case for that but doesn't know how to proceed the string
case
when (match the string ) then (value after the "=")
else (hardcoded value)
end
In Oracle, you can use:
SELECT value,
CASE
WHEN start_pos = 0
THEN NULL
ELSE SUBSTR(
'||' || value || '||',
start_pos + LENGTH('||Object.Name='),
end_pos - start_pos - LENGTH('||Object.Name=')
)
END AS object_name
FROM (
SELECT value,
INSTR(
'||' || value || '||',
'||Object.Name='
) AS start_pos,
INSTR(
'||' || value || '||',
'||',
INSTR('||' || value || '||', '||Object.Name=')+LENGTH('||Object.Name=')
) AS end_pos
FROM table_name
)
Which, for the sample data:
CREATE TABLE table_name (value) AS
SELECT 'Object.Name=ASDD||Product.Name=DSA' FROM DUAL UNION ALL
SELECT 'Product.Name=QWE||Object.Name=WSXS' FROM DUAL UNION ALL
SELECT 'Storage.Name=12345||Object.Name=WERR||Product.Name=QAZ' FROM DUAL;
Outputs:
VALUE
OBJECT_NAME
Object.Name=ASDD||Product.Name=DSA
ASDD
Product.Name=QWE||Object.Name=WSXS
WSXS
Storage.Name=12345||Object.Name=WERR||Product.Name=QAZ
WERR
db<>fiddle here
Since you changed the tags, in MySQL:
SELECT value,
CASE
WHEN start_pos = 0
THEN NULL
ELSE SUBSTRING(
CONCAT('||', value, '||'),
start_pos + LENGTH('||Object.Name='),
end_pos - start_pos - LENGTH('||Object.Name=')
)
END AS object_name
FROM (
SELECT value,
LOCATE(
'||Object.Name=',
CONCAT('||', value, '||')
) AS start_pos,
LOCATE(
'||',
CONCAT('||', value, '||'),
LOCATE('||Object.Name=', CONCAT('||', value, '||'))
+ LENGTH('||Object.Name=')
) AS end_pos
FROM table_name
) t
db<>fiddle here

How to get count of columns that are having null values for a given row in sql?

I have a table that are having 115 columns.
Out of 7 columns I need to get the count of columns that are having not null values for a given row.
One method is to use case and +:
select t.*,
( (case when col1 is not null then 1 else 0 end) +
(case when col2 is not null then 1 else 0 end) +
(case when col3 is not null then 1 else 0 end) +
(case when col4 is not null then 1 else 0 end) +
(case when col5 is not null then 1 else 0 end) +
(case when col6 is not null then 1 else 0 end) +
(case when col7 is not null then 1 else 0 end)
) as cnt_not_nulls_in_row
from t;
In MySQL, this can be simplified to:
select t.*,
( (col1 is not null ) +
(col2 is not null ) +
(col3 is not null ) +
(col4 is not null ) +
(col5 is not null ) +
(col6 is not null ) +
(col7 is not null )
) as cnt_not_nulls_in_row
from t;
You may first query the given row from the table using the primary key and the use COUNT to count the number of columns from the queried row having null value, as follows:
WITH derived_row as
(SELECT col1, col2, col3, col4, col5, col6, col7 FROM table WHERE primary_key=key)
SELECT COUNT(CASE
WHEN col1 IS NULL THEN 1
WHEN col2 IS NULL THEN 1
WHEN col3 IS NULL THEN 1
WHEN col4 IS NULL THEN 1
WHEN col5 IS NULL THEN 1
WHEN col6 IS NULL THEN 1
WHEN col7 IS NULL THEN 1
END) AS null_column_count
FROM derived_row;

Flattening a Table in prep for Json

Maybe it's that I'm tired but this is escaping me.
Let's say that I want to flatten this table:
a_id a_val b_id b_val c_id c_val d_id d_val
1 a 10 b 100 c 1000 f
1 a 20 d 200 g null null
2 e 30 h 300 i null null
2 j 40 k null null null null
3 l null null null null null null
Into this query result:
id mystring
1, (1:a,10:b,100:c,1000:f),(1:a,20:d,200:g)
2, (2:e,30:h,300:i),(2:j,40:k)
3, (3:l)
The table only renders four levels deep (a, b, c, d) so no dynamic sql issue.
Now I'd usually just use GROUP_CONCAT(CONCAT(...)) but that won't work with the Nulls present. And maybe using coalesce somehow will solve this but... I feel pretty stupid at the moment... and I can't figure it out.
Unfortunately I can't use mysql json services on this installation so I need to construct the data. thanks.
The solution here will probably just be a combination of clever concatenation and IFNULL calls. My shot in the dark:
SELECT a_id, GROUP_CONCAT(CONCAT('(',
a_id, ':', a_value, ',',
IFNULL(b_id, ''), IF(b_id IS NOT NULL, ':', ''), IFNULL(b_val, ''),
...repeat for c and d
')'
) SEPARATOR ',')
FROM table
GROUP BY a_id;
select a_id as id,
group_concat(concat(
case isnull(a_id) when true then '' else '(' end,
coalesce(a_id, ''),
case isnull(a_id) when true then '' else ':' end,
coalesce(a_val, ''),
case isnull(b_id) when true then '' else ',' end,
coalesce(b_id, ''),
case isnull(b_id) when true then '' else ':' end,
coalesce(b_val, ''),
case isnull(c_id) when true then '' else ',' end,
coalesce(c_id, ''),
case isnull(c_id) when true then '' else ':' end,
coalesce(c_val, ''),
case isnull(d_id) when true then '' else ',' end,
coalesce(d_id, ''),
case isnull(d_id) when true then '' else ':' end,
coalesce(d_val,''),
case isnull(a_id) when true then '' else ')' end
) separator ',')
from table
group by a_id;

How to update the first non null column of each row?

I have following solution
Select Col1 = Case when Col1 is null then 'update'
else Col1
,Col2 = Case when Col1 is null then Col2
when Col2 is null then 'update'
else Col2
,Col3 = Case when Col2 is null then Col3
when Col3 is null then 'update'
else Col3
.... and so on
Just wondering if anyone has better solution.
Your solution is not correct.
SQL does not works this way, you need to check all preceding columns.
(And you forgot ENDs for your CASEs)
DECLARE #T TABLE(
col1 sysname NULL
,col2 sysname NULL
,col3 sysname NULL
)
INSERT INTO #T
SELECT NULL, 'N', NULL
-- Incorrect
Select Col1 = Case when Col1 is null then 'update'
else Col1
END
,Col2 = Case when Col1 is null then Col2
when Col2 is null then 'update'
else Col2
END
,Col3 = Case when Col2 is null then Col3
when Col3 is null then 'update'
else Col3
END
FROM #T
-- Dull, but correct
SELECT
Col1 = ISNULL(Col1, 'update')
,col2 = CASE
WHEN Col1 IS NOT NULL
AND Col2 IS NULL
THEN 'update'
ELSE Col2
END
,col3 = CASE
WHEN Col1 IS NOT NULL
AND Col2 IS NOT NULL
AND Col3 IS NULL
THEN 'update'
ELSE Col3
END
FROM #T

Multiple IF statements on MYSQL

I'm trying to Display somes values in my database result, I am using this code but I can not succeed:
SELECT
item_code,
IF(category_code = 'HERR1', 'NO', 1) OR (category_code = 'COLN5', 'NO', 2) AS category_code,
item_name,
item_quantity
FROM qa_items
EDIT :
I Want to display for example:
If category_code = 'HERR1'
Display = 1
else if category_code = 'COLN5'
Display = 2
End If
If anyone has any idea, would greatly appreciate it
I'd rather use CASE :
SELECT item_code,
CASE category_code
WHEN 'HERR1' THEN 1
WHEN 'COLN5' THEN 2
ELSE 'NO'
END as category_code, item_name, item_quantity
FROM qa_items
But IF will also work : IF(category_code='HERR1',1, IF(category_code='COLN5',2,'NO'))
You need to nest the if statements
SELECT item_code, IF(category_code = 'HERR1', 'NO', IF(category_code = 'COLN5', 1, 2)) AS category_code, item_name, item_quantity FROM qa_items
Then the first if will fail and the nested if will evaluate
Is this what you were after?
SELECT
item_code,
CASE category_code
WHEN 'HERR1' THEN 1
WHEN 'COLN5' THEN 2
ELSE 'NO'
END AS category_code,
item_name,
item_quantity
FROM qa_items
Try the following
SELECT item_code, CASE category_code WHEN 'HERR1' THEN 1 WHEN 'COLN5' THEN 0 ELSE 'NONE' END AS category_code, item_name, item_quantity FROM qa_items
You can try this.
Use IF in select query and update the table you want ;)
create table student(marks int,grade char);
insert into student values(200,null),(120,null),
(130,null);
UPDATE student a
INNER JOIN (select s.marks, IF(s.marks>=200,'A',IF(s.marks>=130,'B','P')) AS Grade from student s) b on a.marks= b.marks
SET a.Grade = b.Grade;
SELECT MOBILE,
CASE (SUBSTRING(mobile, LENGTH(MOBILE), 1)) WHEN ','
THEN SUBSTRING(mobile, 1, LENGTH(MOBILE) - 1)
ELSE SUBSTRING(mobile, 1, LENGTH(MOBILE))
END AS newmobile
FROM (SELECT CONCAT(IFNULL(`mob1`, ''), IF(`mob1` IS NULL, '', ','),
IFNULL(`mob2`, ''), IF(`mob2` IS NULL, '', ','),
IFNULL(`mob3`, ''), IF(`mob3` IS NULL, '', ','),
IFNULL(`mob4`, ''), IF(`mob4` IS NULL, '', ','),
IFNULL(`mob5`, ''), IF(`mob5` IS NULL, '', ','),
IFNULL(`mob6`, ''))
AS mobile
FROM `temp_consignordata`) AS T
SELECT item_code,
-- First if
IF(category_code = 'HERR1', 1,
-- second else IF
IF(category_code = 'COLN5', 2,
-- last else
'NO')
AS category_code,
item_name,
item_quantity
FROM qa_items;
Explanation
first if evalutes for value 'HERR1' and if found assigns 1
Second (else ) IF evalues for Value 'COLN5' and if found assigns 2
Last (else) default case assigns 'NO'
to category_code