Excluding a value when null is present in the column - sql

I want to filter the table without the row c
column 1
column 2
a
100
b
200
c
50
null
200
Desired output
column 1
column 2
a
100
b
200
null
200
I tried
select *
from table
where column1 <> 'c'
But since I can compare with null, I'm getting the wrong output. How do I deal with this?

You need to handle the null as follows:
select * from table where column1 <> 'c' or column1 is null
Or you can use the coalesce function as follows:
select * from table where coalesce(column1,'cc') <> 'c'
Coalesce will replace the null value in column1 with the value provided as the second argument. I have used the value which is not equal to 'c' so records with column1 as null will pass this condition

ANSI SQL, DISTINCT predicate.
select *
from table
where column1 is distinct from 'c'
However, not supported by all dbms products.

Related

SQL literal value that is alternative to NULL

Are there other special literal values besides NULL in SQL / PostgresQL?
NULL is nice in that we can interpret NULL as the concept of "nothing" (i.e. missing, not available, not asked, not answered, etc.), and data columns of any type can have NULL values.
I would like another value that I can interpret as representing another concept (here the idea of "everything"), in the same result set.
Is there another special value that I can return in a query, which like NULL doesn't type conflict?
Basically anything that doesn't throw ERROR: For 'UNION', types varchar and numeric are inconsistent in this toy query:
select 1 as numeral, 'one' as name UNION ALL
select 2 as numeral, 'two' as name UNION ALL
select NULL as numeral, NULL as name UNION ALL
select -999 as numeral, -999 as name UNION ALL -- type conflict
select '?' as numeral, 'x' as name -- type conflict
Here,
-999 doesn't work as its type conflicts with varchar columns
'~' doesn't work as its type conflicts with numeric columns
NULL doesn't work as it needs
More specifically here's my actual case, counting combinations of values and also include "Overall" rows in the same query. Generally I won't know or control the types of columns A, B, C in advance. And A, B, or C might also have NULL values which I would would still want to count separately.
SELECT A, COUNT(*) FROM table GROUP BY 1
UNION ALL
SELECT ?, COUNT(*) FROM table GROUP BY 1
and get a result set like:
A
COUNT
NULL
2
1
3
2
5
3
10
(all)
20
SELECT B, COUNT(*) FROM table GROUP BY 1
UNION ALL
SELECT ?, COUNT(*) FROM table GROUP BY 1
and get a result set like:
B
COUNT
NULL
2
'Circle'
3
'Line'
5
'Triangle'
10
(all)
20
You can use function CAST to convert the format to VARCHAR to be considered as string.
NOTE: Thanks to the comments above, I should completely rephrase this question as "How to COUNT/GROUP BY with ROLLUP using multiple columns of mixed/arbitrary/unknown types, and differentiate true NULL values from ROLLUP placeholders?"
The correct answer I believe is provided by #a_horse_with_no_name: use ROLLUP with GROUPING.
Below is is just me drafting that more completely with a revised example:
This toy example has an integer and a string
WITH table AS (
select 1 as numeral, 'one' as name UNION ALL
select 2 as numeral, 'two' as name UNION ALL
select 2 as numeral, 'two' as name UNION ALL
select NULL as numeral, NULL as name UNION ALL
select NULL as numeral, NULL as name UNION ALL
select NULL as numeral, NULL as name
)
select name, numeral, COUNT(*), GROUPING_ID()
FROM table
GROUP BY ROLLUP(1,2)
ORDER BY GROUPING_ID, name, numeral ;
It returns the following result:
numeral
name
count
grouping_id
note
NULL
NULL
3
0
both are true NULLs as grouping is 0
1
one
1
0
2
two
2
0
NULL
NULL
3
1
first is a true NULL, second is a ROLLUP
1
NULL
1
1
2
NULL
2
1
NULL
NULL
6
3
both NULLs are ROLLUPs

Compare nulll value with non null value SQL

I have two columns as below:
Column A
Column B
A1
NULL
A1
A1
B1
C1.
When i query these columns as below :
SELECT Column A, Column B
from table
where Column A != Column B
i am expecting the following result:
Column A
Column B
A1
NULL
B1.
C1
But my query is only giving me the second line as result.
Consider below
select *
from your_table
where columnA is distinct from columnB
with output
Null values do not participate in equality operations as there is no value to compare with.
You will need to include a check for null into your comparisoon statement.
SELECT Column A, Column B from table where ISNULL(Column A,0) <> ISNULL(Column B,0)
null in SQL equals unknown
It could also have A1 as value, therefore it will not show up if you check if A1 is not null
You can use below workaround
select * from your_table
except distinct
select * from your_table
where columnA = columnB
with output
SELECT * from Your_table where IFNULL(`Column A`, 'NULL') != IFNULL(`Column B`, 'NULL')
IFNULL(expression, alt_value) function returns the value of the expression if it's not NULL and returns alt_value when expression is NULL.
So, from the above query, Column A and Column B will have the string value of 'NULL' when the column has the NULL value so they can still be comparable.

Rename category in the column in SQL Server

Here is the query
select col1
from table
col1 contains these category values:
A
B
C
NULL
How can I rename null category to D?
If you want to make the change permanent
UPDATE table
SET col1 = 'D'
WHERE col1 IS NULL
From then on you can simply query with ...
SELECT col1
FROM table
... to get the desired result.
If there is more than one row having a NULL in col1, you need to filter by a unique key, preferably by the primary key (which every table should have by the way). Let's say you have a table like
id (PK) col1
--- ----
1 'A'
2 'B'
3 'C'
4 NULL
5 NULL
then you can fix it with
UPDATE table SET col1 = 'D' WHERE id = 4;
UPDATE table SET col1 = 'E' WHERE id = 5;
unless you can calculate the new value from another column, e.g.:
UPDATE table
SET col1 = UPPER(LEFT(name, 1))
Try this : ISNULL( ) function is used to replace NULL value with another value
select isnull(col1,'D') as col1
from table
SQL Server uses ISNULL().
SELECT ISNULL(value_to_check, use_this_instead_if_valuetocheck_is_null)
For your code:
select ISNULL(col1, 'D') AS col_name
from table
However, this will happen across the board for this column. You can't use this to make a sequence, like D then E then F. Any NULL value you come across in this column will change to D.

Where Clause 'drops' more rows than expected

I have a SQL Server 2008 R2 query that was returning "hypothetically" 100 rows. I'm actually working with 7k - 8k rows.
The Where clause is something like this:
Where Col_a = 'Y'
And Col_b = 'N'
And Col_c = 'X'
and 25 of the rows had 'P' in Col_d.
I added:
And Col_d = 'P'
and the query returned the expected 25 rows.
Then I changed to
And Col_d <> 'P'
I expected to get 75 rows but I got only 50.
I thought adding "And Col_d <> 'P'" would only restrict the rows in which there is a 'P' in Col_d.
Why is that not the case and how do I figure out what else is getting dropped when I say And Col_d <> 'P'?
As I said - I am actually working with larger numbers so it is not that easy to eyeball it.
I'd appreciate any help.
Thanks!
As stated in the comment, null is a special case when it comes to comparisons.
Assume the following data.
id someVal
----
0 null
1 1
2 2
With a query:
select id
from table
where someVal = 1
would return id 1
select id
from table
where someVal <> 1
would return id 2
select id
from table
where someVal is null
would return id 0
select id
from table
where someVal is not null
would return both ids 1 and 2.
If you wanted nulls to be "counted" as values in a = <> comparison, it needs to be cast to something like:
select id
from table
where isNull(someVal, -1) <> 1
returns 0 and 2
Or you can change your ANSI Null setting.
What I want to do is only exclude the rows that have 'P' in Col_d
So in your specific case, because you want to treat null in Col_D as a non P row, your query could look like this:
select *
from someTable
Where Col_a = 'Y'
And Col_b = 'N'
And Col_c = 'X'
And isNull(Col_D, 'someArbitraryValue') <> 'P'
You have to do the above, because as I pointed out throughout the answer and in the links null does not compare the same way as values. You need to make the null something that is not null, (accomplished with isNull(Col_D, 'someArbitraryValue')) or change ANSI NULL setting in order to compare it as equal or not equal to some value.
Or as #Andrew pointed out magic numbers are bad (someArbitraryValue), so you could instead do:
select *
from someTable
Where Col_a = 'Y'
And Col_b = 'N'
And Col_c = 'X'
And (Col_D <> 'P' OR Col_D is null)
Normally I would do the directly above query, I was doing it the other way to mostly point out the differences in null comparison vs a value.

Hiding a row in a table with a query when 3 columns have null values

I am looking for the best way to build a query which would hide the record (row) in the event that three field values (in three different columns) would be null. The code below is giving me a syntax run time error message of 3075. Also, I am not sure if it is causing a problem but the code below is executed from a main form and impacting the subform frmStaticDataSkills02.
sql_get = "SELECT [tblCompetency02].[HighLevelObjective], [tblCompetency04].[Self], [tblCompetency04].[SelfSpecialLanguage], [tblCompetency04].[SelfChecklist], [tblCompetency04].[Team], [tblCompetency04].[TeamSpecialLanguage], [tblCompetency04].[TeamChecklist], [tblCompetency04].[Organisation], [tblCompetency04].[OrganisationSpecialLanguage], [tblCompetency04].[OrganisationChecklist], [tblCompetency02].[Competency] FROM [tblCompetency04] INNER JOIN [tblCompetency02] ON [tblCompetency04].[HighLevelObjective] = [tblCompetency02].[ID] WHERE ([tblcompetency04].[self]<>"" or [tblcompetency04].[team]<>"" or [tblcompetency04].[organisation]<>"")"
Form_frmStaticDataSkills02.Form.RecordSource = sql_get
In a general sense, in a table of N columns, you can explicitly count the number of NULL columns in a table and then add them up and compare the count of nulls to 3 in a where predicate:
SELECT *
FROM MyTable x
WHERE
((IIF(x.COL1 IS NULL, 1 , 0) +
IIF(x.COL2 IS NULL, 1 , 0) +
IIF(x.COL3 IS NULL, 1 , 0) +
IIF(x.COL4 IS NULL, 1 , 0))) <> 3;
(Obviously, keep adding IIF statements for all N columns of the table
This will return the data if not all three columns are NULL:
where not (col1 is null and col2 is null and col3 is null)
This is the same after applying algebra of logic: return the row if any of the three rows is NOT NULL
where col1 is not null or col2 is not null or col3 is not null)
End your query with:
WHERE [column_1] IS NOT NULL AND [column_2] IS NOT NULL AND [column_3] IS NOT NULL
You can do that in your where clause by specifying that all 3 fields should not be NULL, the result set that is returned will not have records where all 3 fields are NULL.
SELECT *
FROM tablename
WHERE
field1 IS NOT NULL AND
field2 IS NOT NULL AND
field3 IS NOT NULL
If you do not want to have rows returned where any one of the columns has null values you would use OR. For example:
SELECT *
FROM tablename
WHERE
field1 IS NOT NULL OR
field2 IS NOT NULL OR
field3 IS NOT NULL