Is a subquery, which is returning no row, equal to NULL? - sql

In SQL Server, if my SELECT statement in a subquery returns no row, is then the result of the subquery equal to NULL? I made some research, but I am not sure about it.
Example:
IF (SELECT TOP 1 CLMN1 FROM SOMETABLE) IS NOT NULL THEN
....
I am asking to understand the behaviour of the if-statement above.

Looks like the answer is yes:
DECLARE #Test TABLE (Id INT)
INSERT INTO #Test VALUES (1)
SELECT * FROM #Test WHERE Id = 2
SELECT CASE WHEN (SELECT * FROM #Test WHERE Id = 2) IS NULL THEN 1 ELSE 0 END
EDIT: after you updated your question I think I should add that instead of checking if there are rows with IS NULL you should use the following that can be better optimised by the server:
IF EXISTS(SELECT * FROM #Test WHERE Id = 2)
BEGIN
-- Whatever
END

NULL means no value, for example that the "box" for a certain column in a certain row is empty. NO ROW means that there are no rows.

No, NULL is a column value that indicates that the value of that column for a given row has no valid value. There would have to be a row returned by your query for that row to contain NULL column values.
A query that returns no rows just means that no rows matched the predicate you used in the query and therefore no data was returned at all.
Edit: After the question was edited, my answer doesn't address the specific case called out in the question. Juan's answer above does.

Related

SQL NOT IN function not returning expected result

Total number of records in table i1450:
Total number with condition where i.BROJ is equal to field REFERENCA in other table:
Shouldn't it return difference between last two results (which is 64) when I use NOT IN in WHERE clause?
Both of columns are of varchar type.
If you have any NULL values in the REFERENCA column from the FpsPmtOrderRQ table then the NOT IN clause will not work as expected - (the reason why)
A solution is to remove NULL values from the result returned by the subselect.
SELECT COUNT(*)
FROM i1450 j
WHERE i.BROJ NOT IN (SELECT REFERENCA FROM FpsPmtOrderRQ WHERE REFERENCA IS NOT NULL)
If the sub-query returns a null value, the IN will not be true. Do NOT EXISTS instead.
select count(*)
from i1450 i
where not exists (select 1 from FpsPmtOrderRQ f
where i.broj = f.REFERENCA)
I think you need to coalesce your field to handle nulls. That is probably why you get 0.
By doing:
where coalesce(I.BROJ,'n/a') not in (select coalesce(REFERENCA,'')
or something similar, you would exclude nulls, and return a proper count.

Selecting from table to insert into another, getting a type error

I have the following query which inserts data into one table after selecting it from another.
The problem is that the data types do not match for one of the columns. I have simplified the query below.
INSERT INTO tbl.LogTable (
[SelPartNo], -- This does not match, see below
)
SELECT TOP 1
IF([SelPartNo] = 'False', NULL, [SelPartNo],
FROM tbl.MyTable
WHERE ID = '20358'
ORDER BY CreateDate DESC
The first SelPartNo is an int and the second is a VarChar. In most instances the SelPartNo for the second one (tbl.MyTable) is NULL or an integer, which I don't think will cause a problem. But in some cases the value is "False", which needs to return NULL.
I have tried an IF statement but I am doing something wrong because it's giving a syntax error and I am unsure if this is the correct approach.
Your code is syntactically incorect...
Try it with
NULLIF([SelPartNo],'False')
This function returns NULL if the two expressions are equal.
Details: https://msdn.microsoft.com/en-us/library/ms177562.aspx
I don't think IF is a function, at least not one which you can use in a SELECT statement. But CASE WHEN ... END is your friend:
INSERT INTO tbl.LogTable (
[SelPartNo]
)
SELECT TOP 1
CASE WHEN [SelPartNo] = 'False' THEN NULL ELSE [SelPartNo] END
FROM tbl.MyTable
WHERE ID = '20358'
ORDER BY CreateDate DESC

SQL SELECT statement within an IF statement

I have a trigger in SQL Server that needs to check on an update the number of rows with a value between a certain amount and do something accordingly. My current code is something like this:
IF EXISTS(SELECT COUNT(id) as NumberOfRows
FROM database
WHERE id = 3 AND value <= 20 and value > 2
GROUP BY id
HAVING COUNT(id) > 18)
-- if true, do something
From what I can tell, the select statement should find the number of rows with a value between 2 and 20 and if there are more than 18 rows, the EXISTS function should return 1 and the query will execute the code within the IF statement.
However, what is happening is that it is always executing the code within the IF statement regardless of the number of rows with a value between 2 and 20.
Any ideas on why this might be? I can post more complete code if it might help.
The reason is that the Exists function is checking the result of the sub-query for existing - are there any rows or not. And, as you return the COUNT, it'll never be not-existing - COUNT returns 0 if there are no rows presented in database.
Try to store the resulting count in a local variable, like in this question:
Using IF ELSE statement based on Count to execute different Insert statements
DECLARE #retVal int
SELECT #retVal = COUNT(*)
FROM TABLE
WHERE COLUMN = 'Some Value'
IF (#retVal > 0)
BEGIN
--INSERT SOMETHING
END
ELSE
BEGIN
--INSERT SOMETHING ELSE
END
I would do it like so (single line):
IF ((SELECT COUNT(id) FROM table WHERE ....)>18) BEGIN
...do something
You can even do between in a single line
IF ((SELECT COUNT(id) FROM table WHERE ....)between 2 and 20) BEGIN
...do something
END
Your subquery is looking for matches in the entire table. It does not limit the results only to those that are related to the rows affected by the update. Therefore, if the table already has rows matching your condition, the condition will be true on any update that affects other rows.
In order to count only the relevant rows, you should either join the database table to the inserted pseudo-table or use just the inserted table (there is not enough information in your question to be sure which is better).

SQL query to get null count from a column

I want to generate a SQL query to get null count in a particular column like
SELECT COUNT (column) AS count
FROM table
WHERE column = null ;
This is returning 0, but I want how many null values are present in that column like
SELECT COUNT (column) AS count
FROM table
WHERE column = 'some value';
which returns the count of the matched records
NULL value is special in that you cannot use = with it; you must use IS NULL instead:
SELECT COUNT (*) AS count FROM table where column IS null ;
This is because NULL in SQL does not evaluate as equal to anything, including other NULL values. Also note the use of * as the argument of COUNT.
You can use a conditional sum()
SELECT sum(case when column is null
then 1
else 0
end) AS count
FROM table
A different query but exact answer check it out
select count(*)-count(column) from table
please vote check this as answer if it helps you
To get exact output you can use below command as well -
SELECT COUNT (*) AS count FROM table where column IS null OR column='';
because some times only '' doesn't counted as NULL.

What is the difference between the IN operator and = operator in SQL?

I am just learning SQL, and I'm wondering what the difference is between the following lines:
WHERE s.parent IN (SELECT l.parent .....)
versus
WHERE s.parent = (SELECT l.parent .....)
IN
will not generate an error if you have multiple results on the subquery. Allows to have more than one value in the result returned by the subquery.
=
will generate an error if you have more than one result on the subquery.
SQLFiddle Demo (IN vs =)
when you are using 'IN' it can compare multiple values....like
select * from tablename where student_name in('mari','sruthi','takudu')
but when you are using '=' you can't compare multiple values
select * from tablenamewhere student_name = 'sruthi'
i hope this is the right answer
The "IN" clause is also much much much much slower. If you have many results in the select portion of
IN (SELECT l.parent .....),
it will be extremely inefficient as it actually generates a separate select sql statement for each and every result within the select statement ... so if you return 'Cat', 'Dog', 'Cow'
it will essentially create a sql statement for each result... if you have 200 results... you get the full sql statement 200 times...takes forever... (This was as of a few years ago... maybe imporved by now... but it was horribly slow on big result sets.)
Much more efficient to do an inner join such as:
Select id, parent
from table1 as T
inner join (Select parent from table2) as T2 on T.parent = T2.parent
For future visitors.
Basically in case of equals (just remember that here we are talking like where a.name = b.name), each cell value from table 1 will be compared one by one to each cell value of all the rows from table 2, if it matches then that row will be selected (here that row will be selected means that row from table 1 and table 2) for the overall result set otherwise will not be selected.
Now, in case of IN, complete result set on the right side of the IN will be used for comparison, so its like each value from table 1 will be checked on whether this cell value is present in the complete result set of the IN, if it is present then that value will be shown for all the rows of the IN’s result set, so let say IN result set has 20 rows, so that cell value from table 1 will be present in overall result set 20 times (i.e. that particular cell value will have 20 rows).
For more clarity see below screen shot, notice below that how complete result set from the right of the IN (and NOT IN) is considered in the overall result set; whole emphasis is on the fact that in case comparison using =, matching row from second table is selected, while in case of IN complete result from the second table is selected.
In can match a value with more than one values, in other words it checks if a value is in the list of values so for e.g.
x in ('a', 'b', 'x') will return true result as x is in the the list of values
while = expects only one value, its as simple as
x = y returns false
and
x = x returns true
The general rule of thumb is:
The = expects a single value to compare with. Like this:
WHERE s.parent = 'father_name'
IN is extremely useful in scenarios where = cannot work i.e. scenarios where you need the comparison with multiple values.
WHERE s.parent IN ('father_name', 'mother_name', 'brother_name', 'sister_name')
Hope this is useful!!!
IN
This helps when a subquery returns more than one result.
=
This operator cannot handle more than one result.
Like in this example:
SQL>
Select LOC from dept where DEPTNO = (select DEPTNO from emp where
JOB='MANAGER');
Gives ERROR ORA-01427: single-row subquery returns more than one row
Instead use
SQL>
Select LOC from dept where DEPTNO in (select DEPTNO from emp
where JOB='MANAGER');
1) Sometimes = also used as comparison operator in case of joins which IN doesn't.
2) You can pass multiple values in the IN block which you can't do with =. For example,
SELECT * FROM [Products] where ProductID IN((select max(ProductID) from Products),
(select min(ProductID) from Products))
would work and provide you expected number of rows.However,
SELECT * FROM [Products] where ProductID = (select max(ProductID) from Products)
and ProductID =(select min(ProductID) from Products)
will provide you 'no result'. That means, in case subquery supposed to return multiple number of rows , in that case '=' isn't useful.