I am writing a simple select subquery statement and it is not giving any result. Neither it is throwing any error.
My Sql query is like this -
select * from Table1
where id in (select ID from Table2 where user = 'xyz')
I tried with exists also, but not showing any result.
Appreciate your help.
It could be that the below subquery returns a empty list because the filter condition where user = 'xyz' doesn't matches any record
select ID from Table2 where user = 'xyz'
The outer query as below doesn't matches the condition where id in ()
select * from Table1 where id in ()
Thus returning an empty result set.
You can convert your posted query to be a INNER JOIN query like
select t1.*
from Table1 t1 join Table2 t2
on t1.id = t2.id
where t2.user = 'xyz';
As a test, try using LIKE operator instead of equality comparison
select * from Table1
where id in (select ID from Table2 where user like '%xyz%')
Related
I am trying to do below
Table 1
Table 2
I am writing a query like below to ensure that if any of the NOT IN satisfies, those records should be filtered out.
SELECT * FROM TABLE1
WHERE TABLE1."DEPTID" NOT IN (SELECT TABLE2."DEPTID" FROM TABLE2)
OR
TABLE1."EMPCOUNTRY" NOT IN (SELECT TABLE2."EMPCOUNTRY" FROM TABLE2)
OR
TABLE1."EMPZONE" NOT IN (SELECT TABLE2."EMPZONE" FROM TABLE2)
But it errors out
What am I doing wrong?
Edited : Exact Query is working with nvl , but result set is not as per requirement.
SELECT * FROM TABLE1 AS T1
WHERE
(
UPPER (T1."DEPTID") NOT IN
(SELECT UPPER (nvl (T2."DEPTID", '')) FROM TABLE2 AS T2)
OR
UPPER (T1."EMPZONE") NOT IN
(SELECT UPPER (nvl (T2."EMPZONE",'')) FROM TABLE2 AS T2)
)
Result - set is not as per requirement, it should filter out if there any DEPTID in the Table2 or if there is any EMPZONE in table 2 or both etc.
What should be the best way to achieve this?
I think the issue is about NULL values coming from the subqueries. Could you try to use something like this?
SELECT * FROM TABLE1 AS T1
WHERE
(
NOT EXISTS (SELECT 1 FROM TABLE2 T2 WHERE equal_null( UPPER(T1."DEPTID"), UPPER(T2."DEPTID")) )
OR
NOT EXISTS (SELECT 1 FROM TABLE2 T2 WHERE equal_null( UPPER(T1."EMPZONE"), UPPER(T2."EMPZONE")) )
);
Also here is a sample to demonstrate why you can't use NOT IN with a subquery returning NULL values:
create table NULL_TABLE ( v varchar);
insert into NULL_TABLE values (NULL),('ABC');
create or replace table MAIN_TABLE ( v varchar);
INSERT INTO MAIN_TABLE values
('Jack'),('Joe'),('ABC');
select * from MAIN_TABLE
where v NOT IN (select v FROM NULL_TABLE);
The last query returns NULL, because we can't determine if a value does not exist in series of numbers where some of them are not known - the last WHERE clause.
When using NOT IN the subquery should not allow null values as reselut, second conditions to happen all at once should be joined with AND instead of OR.
NOT (cond1 OR cond2 OR cond3)
<=>
(NOT cond1) AND (NOT cond2) AND (NOT cond3)
De Morgan's law: "The negation of a disjunction is the conjunction of the negations"
The final query should rather be:
SELECT *
FROM TABLE1 AS T1
WHERE T1."DEPTID" NOT IN (SELECT T2."DEPTID" FROM TABLE2 T2
WHERE T2."DEPTID" IS NOT NULL)
AND T1."EMPCOUNTRY" NOT IN (SELECT T2."EMPCOUNTRY" FROM TABLE2 T2
WHERE T2."EMPCOUNTRY" IS NOT NULL)
AND T1."EMPZONE" NOT IN (SELECT T2."EMPZONE" FROM TABLE2 T2
WHERE T2."EMPZONE" IS NOT NULL);
I would like to add the count result of a 2nd query to the result set which queries the 1st table and connect this subquery with the ID of the 1st Table result. This simplified code explains it:
Select
ID_Field_Table1,
(Select Count(x)
From Table2
Where ID_Field_Table2 = ID_Field_Table1) As mycount
From Table1
What is the correct syntax?
Thanks
This code is simplified but the construction is the same. In my DB the ID_Field_Table2 and ID_Field_Table1 have the same name (let's say ID_Field). If I use this same Name, the SubQuery goes like "...Where ID_Field = ID_Field.." and this always Returns a Reslut, because it is not connecting the queries ("Select a Where x = x" returns any record in the table 2).
Select
ID_Field AS ID1,
(Select Count(x)
From Table2
Where ID_Field = ID1) As mycount
From Table1
It just returns an error, saying that ID1 does not exist.
When I use the original name of the columns (which are the same), the result is wrong
When I us an alias, an error occurs
So I think the query is wrong at all.
Well, you can't use an alias defined in the select clause, but you can use the aliases defined in the from clause:
Select
ID_Field AS ID1,
(Select Count(x)
From Table2
Where ID_Field = t1.ID_Field) As mycount
From Table1 t1
You can also do it without an alias, since the sub query is for a different table:
Select
ID_Field AS ID1,
(Select Count(x)
From Table2
Where ID_Field = Table1.ID_Field) As mycount
From Table1
However, I suspect a query using left join to a derived table as suggested in esta's answer would have better performance.
Something like this?
Select
Table1.ID_Field_Table1,
T2.MYCOUNT
From Table1
LEFT JOIN (SELECT ID_Field_Table2, COUNT(x) AS MYCOUNT FROM TABLE2 GROUP BY ID_FIELD_TABLE2) T2 ON T2.ID_Field_Table2=Table1.ID_Field_Table1
Try This query once it may help you.
Select ID_Field_Table1,COUNT_NBR
cross apply
(
Select Count(x) as COUNT_NBR
From Table2
Where ID_Field_Table2 = ID_Field_Table1
group by ID_Field_Table1
) As mycount
From Table1
I have three tables
table1 -> xt1, yt1, zt1;
table2 -> xt2
table3 -> yt3, zt3
SELECT xt1, yt1, zt1
From table1, table3
Where xt1
NOT IN
(SELECT DISTINCT table1.xt1 FROM table2 INNER JOIN table1 ON
table1.xt1 = Replace(table2.xt2,',',''))
And table1.yt1 = table3.yt3
AND table1.zt1 = table3.zt3
it is working correctly but i take long time.
if i replace NOT IN with Not exists it return empty set.
SELECT xt1, yt1, zt1
From table1, table3
Where Not exists
(SELECT DISTINCT table1.xt1 FROM table2 INNER JOIN table1 ON
table1.xt1 = Replace(table2.xt2,',',''))
And table1.yt1 = table3.yt3
AND table1.zt1 = table3.zt3
the results of the second select should be 6 rows but it returns notiong with not exists.
also if i tried to change the compare part to
table1.xt1 != Replace(table2.xt2,',','') and remove the NOT IN
select it get outof memory error.
So is this the best way to write my query and why it return empty set with Not exists
thank you.
Ok, first of all, I changed your implicit join to an explicit one. Then I fixed the NOT EXISTS so it correlates to the outer table1:
SELECT t1.xt1, t1.yt1, t1.zt1
FROM table1 AS t1
INNER JOIN table3 AS t3
ON t1.yt1 = t3.yt3
AND t1.zt1 = t3.zt3
WHERE NOT EXISTS ( SELECT 1
FROM table2 AS t2
INNER JOIN table1 AS t1_1
ON t1_1.xt1 = REPLACE(t2.xt2,',','')
AND t1_1.xt1 = t1.xt1) ;
which can be simplified further to:
SELECT t1.xt1, t1.yt1, t1.zt1
FROM table1 AS t1
INNER JOIN table3 AS t3
ON t1.yt1 = t3.yt3
AND t1.zt1 = t3.zt3
WHERE NOT EXISTS ( SELECT 1
FROM table2 AS t2
WHERE t1.xt1 = REPLACE(t2.xt2,',','')
) ;
You need to select IN or exist depending upon the size of inner query. when there is a outer query and inner-sub-query, if the result of sub query is small, In is preferred as outer query is selected based upon result of sub-query.
if the result of sub-query is large, exist is preferred as outer query is evaluated first.
I have a SQL query where I have in my where clause a list into a IN condition.
Example of what I mean:
WHERE Id IN (11111,11112)
And what I try to do is the following: I have a linked server query where I have an IN clause.
And I have a subquery where I use a JOIN table to cross data but I need that in the IN condition use the same Id like the main query.
I hope you guys understand what I try to do:
Here's my code:
SELECT
Name,
Street,
Number,
(SELECT loginUser FROM [LinkedServer].[Database].[dbo].[Users] T1
INNER JOIN [LinkedServer].[Database].[dbo].[General] T2
ON T2.IdUser = T1.Id
WHERE T2.Id IN (11111,11112,11113,11114,11115)
)
FROM [LinkedServer].[Database].[dbo].[General]
WHERE Id IN (11111,11112,11113,11114,11115)
i get this error:
Subquery returned more than 1 value. This is not permitted when the
subquery follows =, !=, <, <= , >, >= or when the subquery is used as
an expression.
To reuse same set of ids you could use Table Variable.
DECLARE #T TABLE(ID INT);
INSERT INTO T
SELECT 11111 UNION ALL SELECT 11112 ....
then
SELECT * FROM
(SELECT Varchar1,
Varchar2,
Varchar3, loginUser FROM [LinkedServer].[Database].[dbo].[Table] T1
INNER JOIN [LinkedServer].[Database].[dbo].[Table] T2
ON T2.INT1 = T1.INT1
WHERE T2.Id IN (select id from #T)
) AS X WHERE
X.Id IN (select id from #T)
Consider using a join instead of a correlated-subquery:
SELECT General.Name
, General.Street
, General.Number
, Users.loginUser
FROM [LinkedServer].[Database].[dbo].[General]
LEFT
JOIN [LinkedServer].[Database].[dbo].[Users]
ON Users.Id = General.IdUser
WHERE General.Id IN (11111, 11112, 11113, 11114, 11115)
This will return the loginUser where possible.
i have solved it finally.
The Problem was that the subquery havenĀ“t a where condition to extract a specific Id.
Without a WHERE Condition the query return more than 1 value.
What i have done:
Thanks for the advice and his solution Author: "LIUFA".
With a combination of his code and some correction of my code i get the solution.
I have add one more column Id and give it an alias. In the subquery i have done the select from the Temp table
using a where condition. And its Working. Perfect.
Hope that this solution can help somebody to solved a related issue.
Finally Code:
DECLARE #T TABLE(ID INT);
INSERT INTO #T
Select ReferenceId From MyBigData
SELECT,
A.Id,
Name,
Street,
Number,
(SELECT loginUser FROM [LinkedServer].[Database].[dbo].[Users] T1
INNER JOIN [LinkedServer].[Database].[dbo].[General] T2
ON T2.IdUser = T1.Id
WHERE T2.Id IN (SELECT Id FROM #T WHERE Id = A.Id)
)
FROM [LinkedServer].[Database].[dbo].[General]
WHERE Id IN (SELECT Id FROM #T)
I'm wondering if there's any way to optimize the following SELECT query. (Note: I typed this when writing my question for nonexistent tables and I might not have the correct syntax.)
The goal is, if Table2 contains any related rows I want to set the value of the third column to the number of related rows in Table2. Otherwise, if Table3 contains any related rows I want to set the column to the number of related rows in Table3. Otherwise, I want to set the column value to 0.
SELECT Id, Title,
CASE
WHEN EXISTS (SELECT * FROM Table2 t2 WHERE t2.RelatedId = Table1.Id) THEN
(SELECT COUNT(1) FROM Table2 t2 WHERE t2.RelatedId = Table1.Id)
WHEN EXISTS (SELECT * FROM Table3 t3 WHERE t3.RelatedId = Table1.Id) THEN
(SELECT COUNT(1) FROM Table3 t3 WHERE t3.RelatedId = Table1.Id)
ELSE 0
END AS RelatedCount
FROM Table1
I don't like the fact that I'm basically performing the same query twice (in two cases). Is there any way to do what I want while only performing the query once?
Note that this is part of a much larger query with multiple JOINs and UNIONs so it's not easy to take a completely different approach.
This query should perform much better. You are not just performing the same query twice; since they are correlated subqueries, they will run once per row.
SELECT Id, Title,
coalesce(t2.Count, t3.Count, 0) AS RelatedCount
FROM Table1 t
left outer join (
SELECT RelatedId, count(*) as Count
FROM Table2
group by RelatedId
) t2 on t1.Id = t2.RelatedId
left outer join (
SELECT RelatedId, count(*) as Count
FROM Table3
group by RelatedId
) t3 on t1.Id = t3.RelatedId