How can I query rows where the output would be the rows with least null value on the columns?
My data is:
ID | col1 | col2 | col3 | col4
-----------+----------+-----------+-----------+-----------
1 | Null |Null | with value| with value
2 |with value|Null | with value| with value
3 |with value|Null | Null | Null
where the result would be:
ID | col1 | col2 | col3 | col4
-----------+----------+-----------+-----------+-----------
2 |with value|Null | with value| with value
Because id 2 is the record with fewest null values.
Any help will be greatly appreciated. Thanks
You can:
Order rows by number of nulls (ascending)
Limit rows to 1 ( LIMIT 1 )
Your code:
SELECT *
FROM your_table
ORDER BY
CASE WHEN col1 IS NULL THEN 1 ELSE 0 END +
CASE WHEN col2 IS NULL THEN 1 ELSE 0 END +
CASE WHEN col3 IS NULL THEN 1 ELSE 0 END +
CASE WHEN col4 IS NULL THEN 1 ELSE 0 END
LIMIT 1
If you want only one row, then you can do:
select t.*
from t
order by ( (col1 is null)::int + (col2 is null)::int +
(col3 is null)::int + (col4 is null)::int
) asc
fetch first 1 row only;
If you want all such rows, I think I would do:
select t.*
from (select t.*,
dense_rank() over
(order by (col1 is null)::int + (col2 is null)::int +
(col3 is null)::int + (col4 is null)::int
) as null_ranking
from t
) t
where null_ranking = 1;
Related
Can someone please help me on how to select only the rows which has not null value of a column where that column can have null or not null values for the same id
I have a table like this
I need an output like this
Your description is not very clear. If I do understand correctly your requirement, you want only 1 row per col1. Choose the row with most not null value ?
select *
from
(
select *, rn = row_number() over (partition by col1
order by 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
desc)
from a_table
) d
where rn = 1
I want to write a query creating a calculated column based on evaluating whether several existing columns are true.
For example, if I wanted the output of the column to be 'No' if any 3 or more of 7 columns happen to be null, 'Maybe' if any 2 of them happens to be null, and "Yes" if any one of them happens to be null. A case statement seems like it would require each possible combination of columns to be enumerated.
I looked into creating a local variable, and then setting/redefining it within a select statement, but I can't find anything about what syntax can do this (assuming it's possible). What is the way to do this?
It's not pretty, but here's an option:
ALTER TABLE dbo.Table ADD CalculatedColumn AS (
CASE (CASE WHEN col_a IS NULL THEN 1 ELSE 0 END + CASE WHEN col_b IS NULL THEN 1 ELSE 0 END + ...)
WHEN 1 THEN 'Yes'
WHEN 2 THEN 'Maybe'
ELSE 'No' --3 or more
END
);
You could also add a case for 0, however you wanted to handle that.
From a query perspective, you can try something like the following:
-- Create a mock-up table.
DECLARE #Data table (
col1 varchar(10),
col2 varchar(10),
col3 varchar(10),
col4 varchar(10),
col5 varchar(10),
col6 varchar(10),
col7 varchar(10),
id int IDENTITY ( 1, 1 )
);
-- Insert some mock data.
INSERT INTO #Data VALUES
( 'val', 'val', 'val', 'val', NULL, NULL, NULL ),
( 'val', 'val', 'val', 'val', 'val', NULL, NULL ),
( 'val', 'val', 'val', 'val', 'val', 'val', NULL );
-- Query data and return Yes, No, Maybe based on the number of null columns.
;WITH col_data AS (
SELECT
id,
CASE WHEN col1 IS NULL THEN 1 ELSE 0 END
+ CASE WHEN col2 IS NULL THEN 1 ELSE 0 END
+ CASE WHEN col3 IS NULL THEN 1 ELSE 0 END
+ CASE WHEN col4 IS NULL THEN 1 ELSE 0 END
+ CASE WHEN col5 IS NULL THEN 1 ELSE 0 END
+ CASE WHEN col6 IS NULL THEN 1 ELSE 0 END
+ CASE WHEN col7 IS NULL THEN 1 ELSE 0 END
AS null_sum
FROM #Data
)
SELECT
id,
null_sum,
CASE
WHEN null_sum <= 1 THEN 'Yes'
WHEN null_sum <= 2 THEN 'Maybe'
ELSE 'No'
END AS msg
FROM col_data;
RETURNS
+----+----------+-------+
| id | null_sum | msg |
+----+----------+-------+
| 1 | 3 | No |
| 2 | 2 | Maybe |
| 3 | 1 | Yes |
+----+----------+-------+
I have a table say T_myTable it has 5 columns and all have some values either true or false.
--------------------------------
col1 | col2 | col3 | col4 | col5
--------------------------------
true | false|false|true |false
false| true |false|false|false
true | false|false|true |false
false| false|false|true |false
I want to get result as:-
col1 | col2 | col3 | col4 | col5
--------------------------------
2 | 3 |4 |1 |4
Where these numbers here are numbers of false.
Also true and false are varchar.
This:
SELECT SUM(CASE WHEN Col1 = 'false' THEN 1 ELSE 0 END) AS Col1
, SUM(CASE WHEN Col2 = 'false' THEN 1 ELSE 0 END) AS Col2
, SUM(CASE WHEN Col3 = 'false' THEN 1 ELSE 0 END) AS Col3
, SUM(CASE WHEN Col4 = 'false' THEN 1 ELSE 0 END) AS Col4
, SUM(CASE WHEN Col5 = 'false' THEN 1 ELSE 0 END) AS Col5
FROM T_myTable
Try this:
SELECT SUM(CASE col1 WHEN 'false' THEN 1 ELSE 0 END),
SUM(CASE col2 WHEN 'false' THEN 1 ELSE 0 END),
SUM(CASE col3 WHEN 'false' THEN 1 ELSE 0 END),
SUM(CASE col4 WHEN 'false' THEN 1 ELSE 0 END),
SUM(CASE col5 WHEN 'false' THEN 1 ELSE 0 END)
FROM T_myTable
One of the most interesting way is to:
unpivot data to be able to filter data
pivot data again to get count of 'false'
Check this:
SELECT [col1],[col2],[col3],[col4],[col5]
FROM (
SELECT MyVal, ColName
FROM (
SELECT *
FROM T_myTable
) AS pvt
UNPIVOT(MyVal FOR ColName IN ([col1],[col2],[col3],[col4],[col5])) AS unpvt
WHERE MyVAl = 'false'
) As DT
PIVOT (COUNT(MyVal) FOR ColName IN ([col1],[col2],[col3],[col4],[col5])) AS PT
Result:
col1 col2 col3 col4 col5
2 3 4 1 4
I have a SQL table like this
col1 col2 col3
1 0 1
1 1 1
0 1 1
1 0 0
0 0 0
I am expecting output as like this
col1 col2 col3 NewCol
1 0 1 SL,PL
1 1 1 SL,EL,PL
0 1 1 EL,PL
1 0 0 SL
0 0 0 NULL
The condition for this is if col1>0 then SL else ' ', if col2>0 EL else ' ', if col3>0 PL else ' '
I tried to use Concatenate many rows into a single text string? but didn't able to achieve the desired result properly
I have tried It is working fine with a message
Invalid length parameter passed to the LEFT or SUBSTRING function.
WITH CTE AS (
SELECT col1, col2, col3,
CASE WHEN col1 > 0 THEN 'SL,' ELSE '' END +
CASE WHEN col2 > 0 THEN 'EL,' ELSE '' END +
CASE WHEN col3 > 0 THEN 'PL,' ELSE '' END AS NewCol
FROM Employee
)
SELECT col1, col2, col3,
substring(NewCol, 1, len(NewCol) - 1) AS NewCol
FROM CTE
But again my last condition is not matching if all columns is 0 then I have to show NULL as per desired output.
Find the attach fiddle http://sqlfiddle.com/#!6/2bd6a/1
The issue with your code example is that when all columns are 0 then the length is 0 and the substring function will throw an error.
Use nullif to fix it: substring(NewCol, 1, len(nullif(NewCol,'')) - 1) AS NewCol
You could also change to appending the delimiter on the front and use STUFF.
STUFF('',1,1,'') will return NULL rather than an error.
WITH
Employee(col1, col2, col3) AS (
SELECT 1,1,1 UNION ALL
SELECT 0,0,0
),
CTE AS (
SELECT col1, col2, col3,
CASE WHEN col1 > 0 THEN ',SL' ELSE '' END +
CASE WHEN col2 > 0 THEN ',EL' ELSE '' END +
CASE WHEN col3 > 0 THEN ',PL' ELSE '' END AS NewCol
FROM Employee
)
SELECT col1,
col2,
col3,
STUFF(NewCol, 1, 1, '')
FROM CTE
Returns
+------+------+------+------------------+
| col1 | col2 | col3 | (No column name) |
+------+------+------+------------------+
| 1 | 1 | 1 | SL,EL,PL |
| 0 | 0 | 0 | NULL |
+------+------+------+------------------+
You have to check with NULLIF to do this trick
Two ways
SELECT col1, col2, col3,
nullif(CASE WHEN col1 = 1 THEN 'SL,' ELSE '' END +
CASE WHEN col2 = 1 THEN 'EL,' ELSE '' END +
CASE WHEN col3 = 1 THEN 'PL,' ELSE '' END,'') AS NewCol
FROM Employee
OR
SELECT
col1,
col2,
col3,
substring(nullif(NewCol,''), 1, len(NewCol) - 1) AS NewCol
FROM
CTE
I have a sql in db2 as below:
SELECT distinct KEY_COL, MY_TYPE1,
CASE WHEN MY_TYPE2 = 'ONE' THEN COL1 ELSE '' END AS NEWCOL1,
CASE WHEN MY_TYPE2 = 'ONE' THEN COL2 ELSE '' END AS NEWCOL2,
CASE WHEN MY_TYPE2 = 'TWO' THEN COL1 ELSE '' END AS NEWCOL3,
CASE WHEN MY_TYPE2 = 'TWO' THEN COL2 ELSE '' END AS NEWCOL4
FROM MYSCHEMA.MYTABLE
As clear from above query, based on MY_TYPE2 colums in MYSCHEMA.MYTABLE, the new column values are decided.
If the MY_TYPE2 is one, col1 and col2 goes to newcol1 and newcol2 respectively for given key and MY_TYPE1 column. But if the MY_TYPE2 is two for same key and MY_TYPE1, then col1 and col2 goes to newcol3 and newcol4.
The output table looks something like below:
KEY_COL | MY_TYPE1 | NEWCOL1 | NEWCOL2 | NEWCOL3 | NEWCOL4
=========================================================
1 T1 1 2
1 T1 4 3
1 T2 2 3
1 T2 4 1
========================================================
However, I want a single row based on MY_TYPE1 column as below:
KEY_COL | MY_TYPE1 | NEWCOL1 | NEWCOL2 | NEWCOL3 | NEWCOL4
=========================================================
1 T1 1 2 4 3
1 T2 2 3 4 1
========================================================
How to modify the query to achieve above result ?
Thanks for reading!
select key_col, my_type1, max(newcol1), max(newcol2), max(newcol3), max(newcol4)
from
(
SELECT distinct KEY_COL, MY_TYPE1,
CASE WHEN MY_TYPE2 = 'ONE' THEN COL1 ELSE '' END AS NEWCOL1,
CASE WHEN MY_TYPE2 = 'ONE' THEN COL2 ELSE '' END AS NEWCOL2,
CASE WHEN MY_TYPE2 = 'TWO' THEN COL1 ELSE '' END AS NEWCOL3,
CASE WHEN MY_TYPE2 = 'TWO' THEN COL2 ELSE '' END AS NEWCOL4
FROM MYSCHEMA.MYTABLE
) definedTable
group by key_col, my_type1
select KEY_COL ,max(MY_TYPE1),max(NEWCOL1),max(NEWCOL2),max(NEWCOL3),max(NEWCOL4)
from table
group by KEY_COL