Query two tables - return Items that are not in both - sql

I have two tables like this :
TableA
Id | ProjectId | JobId
TableB
Id | Title
I want to write a query returning TableB Ids that are not in TableA with ProjectId = 2.
I've written a query like
Select B.Id
From TableB B
Right Join TableA A On B.Id = A.JobId
Where B.JobId Is Null And A.ProjectId = 2
But it returns zero output.
Thanks

I would use EXISTS here:
SELECT b.Id
FROM TableB b
WHERE NOT EXISTS (SELECT 1 FROM TableA a WHERE a.JobId = b.Id AND a.ProjectId = 2);
Reading in English terms, the above says to select every Id in TableB such that we cannot find an equal Id in TableA whose ProjectId is also 2.
Query edited

Related

SQL Server: how can I count values in one field different from another, with multiple values for same identifier?

I have two tables with one common column, and an identifying value that can be duplicate (several observations of same document).
An example:
TableA:
A_identifier | Value
-------------+-------
1 | A
1 | B
TableB:
B_identifier | A_identifier | Value
-------------+--------------+-------
1 | 1 | A
2 | 1 | B
3 | 1 | B
4 | 1 | C
The above example illustrates the type of situation I am looking for in my data - we have a case in TableA with multiple values, of which some are the same in TableB and some are not. So TableA.Value and TableB.Value represent the same concept.
I want to know for each TableA.A_identifier, how many rows of TableB have different values than TableA.Value. If there was only one observation per A_identifier, this could be solved with a not, but the multiple possible values prevent this.
What I have thought about doing is something like this (which does not work):
select distinct
b.B_identifier, a.A_identifier
from
TableB b
join
TableA a in b.A_identifer = a.A_identifier and b.Value != a.Value
While the query technically works, it returns the wrong result - it counts all the cases where the values in TableA and TableB are different in a given row. However, I want it to only count the values in TableB which are not present at all in TableA for each A_identifier.
I tried replacing the != with not in which is what I would do for a static parameter. This syntax is not supported.
I hope my question makes sense, and that somebody can help. Thank you in advance.
Try this query if it works for you,
SELECT COUNT(b.A_identifier)
FROM TableB b
LEFT JOIN TableA a
ON b.A_identifier = a.A_identifier
AND b.Value = a.Value
WHERE a.A_identifier IS NULL -- filters out inexisting value
AND EXISTS (SELECT 1
FROM TableA c
WHERE b.A_identifier = c.A_identifier) -- shows only A_identifier
-- that is present in TableA
However, if you want to get the count for each Value
SELECT b.A_identifier, b.Value, TOTAL_COUNT = COUNT(b.A_identifier)
FROM TableB b
LEFT JOIN TableA a
ON b.A_identifier = a.A_identifier
AND b.Value = a.Value
WHERE a.A_identifier IS NULL
AND EXISTS (SELECT 1
FROM TableA c
WHERE b.A_identifier = c.A_identifier)
GROUP BY b.A_identifier, b.Value
Use NOT EXISTS
select t1.A_identifier, count(t2.value)
from TableA t1
left join TableB t2 on t1.A_identifier = t2.A_identifier and
NOT EXISTS (
select 1
from TableA t3
where t3.A_identifier = t2.A_identifier and
t3.Value = t2.Value
)
group by t1.A_identifier
How about the following SQL?
select distinct TableA.A_identifier,
(select count(*) from TableB
where TableB.A_identifier = TableA.A_identifier
and not exists(
select * from TableA where A_identifier = TableB.A_identifier
and Value = TableB.Value)
)
as TableB_Rows
from TableA

SQL: group function is not allowed here

I have this query
SELECT * FROM TABLEA A
INNER JOIN TABLEB B ON A.ID = B.ID AND COUNT(B.*) < 4
WHERE A.STATUS = 0
In tablea, ID will have 2 row of data(2 entries), but in tableb the same ID will have upto 4 rows of data. I am trying to get the ID that has less than 4 rows of data in tableb and display that result.
so if ID 12345 is having only 2 rows of data in tableb, display that result. IF ID 98765 has 4 rows of data in tableb, ignore this entry.
But when i try the above query it says "group function is not allowed here". Please can someone help.
You can not use count() without goup by or having clause. In your case you need having
SELECT * FROM TABLEA A
INNER JOIN TABLEB B ON A.ID = B.ID
WHERE A.STATUS = 0
having COUNT(B.*) < 4
see the sqlfiddle
write it the way you would say it...
"I am trying to get the ID that has less than 4 rows of data in tableb and display that result"
SELECT * FROM TABLEA a
JOIN TABLEB b ON b.ID = a.ID
WHERE A.STATUS = 0
and (Select count(*) from TABLEB
where id = a.Id) < 4
it's not clear, but if you also only want Ids which have 2 or more rows in TableA:
SELECT * FROM TABLEA a
JOIN TABLEB b ON b.ID = a.ID
WHERE A.STATUS = 0
and (Select count(*) from TABLEB
where id = a.Id) < 4
and (Select count(*) from TABLEA
where id = a.Id) > 1

Getting data from one table to another table using join

I have a table name "a"
Id name
1 abc
2 xyz
3 mmm
4 xxx
and Other table name is "b"
Id suId
3 2
3 1
My requirement is get detail from "a" table from "b" table where id=3. Any help?
SELECT a.Id, a.name, b.Id, b.suId FROM b JOIN a ON b.suId = a.Id WHERE b.Id = 3;
I wont recommend join for this kind of scenarios(you want all details from Table A whose ids are in Table B suId column, where Table B id should be 3., Its bad English but hope you got me and may be i got you too.)
SELECT a.name FROM a
WHERE
a.id IN(SELECT b.suId FROM b WHERE b.id = 3);
If you want to use join only then,
SELECT a.name FROM a,b
WHERE a.id = b.suId
AND
b.id = 3;
Simple answer:
SELECT a.Id,a.name FROM a,b
WHERE a.Id=b.suId AND b.Id=3
It will give you the result:
Id Name
1 abc
2 xyz
See result in SQL Fiddle
This should get the job done:
SELECT * FROM table_a a JOIN table_b b ON b.suId = a.Id WHERE b.Id = 3;
You can try this...You can try different JOIN clauses like INNER JOIN, LEFT OUTER JOIN or just simply JOIN etc. You will get different number of rows depending on field connections from 1 table to the other.
SELECT T1.*
FROM a T1
INNER JOIN b T2
ON T1.Id = T2.Id
WHERE T1.Id='3'

Searching Unique Id in Multiple Tables

I have a Scenario where i am required to search unique id in Mutiple tables and assign a level based on where it exist.
Table Hierarchy
TableA
TableB
TableC
Table B holds primary key of table A and Table C holds the Primary of TableB
I need to have a function that takes Id as parameter and Searches that Id in this Table Hierarchy and Return Level i-e If it exist in TableA Level should be One. If it exists in TableB Level should be 2 and if it's in TableC then level should be 3
Here's one way:
SELECT CASE WHEN EXISTS(SELECT 1 FROM TableC WHERE id = #id) THEN '3'
WHEN EXISTS(SELECT 1 FROM TableB WHERE id = #id) THEN '2'
WHEN EXISTS(SELECT 1 FROM TableA WHERE id = #id) THEN 'One'
END AS "Level"
Assuming you want to return the highest level, 3 being the highest for TableC, then something like this should work using the CASE statement:
SELECT
CASE
WHEN C.Id IS NOT NULL THEN 3
WHEN B.Id IS NOT NULL THEN 2
WHEN A.Id IS NOT NULL THEN 1
END as Level
FROM (SELECT #Id as Id) H
LEFT JOIN TableA A ON H.Id = A.Id
LEFT JOIN TableB B ON H.Id = B.Id
LEFT JOIN TableC C ON H.Id = C.Id
Where #Id is the Id of the value you are searching for, for example SELECT 1 as Id.
Good luck.
You need a query that looks like this:
SELECT 1 FROM TableA WHERE id = {0}
UNION ALL
SELECT 2 FROM TableB WHERE id = {0}
UNION ALL
SELECT 3 FROM TableC WHERE id = {0}
The advantage to this over "WHEN" statements is that a) I don't like WHEN statements, and b) if a key exists in multiple tables, this returns a record for each, giving you the opportunity to build program logic around handling that case.

SQL: select all unique values in table A which are not in table B

I have table A
Id | Name | Department
-----------------------------
0 | Alice | 1
0 | Alice | 2
1 | Bob | 1
and table B
Id | Name
-------------
0 | Alice
I want to select all unique Ids in table A which do not exist in table B. how can I do this?
select distinct id
from TableA a
where not exists (
select id
from TableB
where id = a.id
)
Just to provide a different solution than NOT IN :
SELECT DISTINCT A.Id
FROM A
LEFT OUTER JOIN B
ON A.Id = B.Id
WHERE B.Id IS NULL
The "good" solution is usually MINUS or EXCEPT, but MySQL doesn't support it.
This question was asked a few time ago and someone posted an article comparing NOT IN, NOT EXISTS and LEFT OUTER JOIN ... IS NULL. It would be interesting if someone could find it again!
The most efficient answer is to use a left join, as using "NOT IN" can sometimes prevent a query from using an index, if present.
The answer in this case would be something like
SELECT DISTINCT
*
FROM
TableA a
LEFT JOIN
TableB b
ON
a.Id = b.Id
WHERE
b.Id IS NULL
Alternatively, this is more readable than a left join, and more efficient than the NOT IN solutions
SELECT * FROM TableA a where NOT EXISTS (SELECT * FROM TableB where Id = a.Id)
I'd use a NOT EXISTS Like this:
SELECT A.Id
FROM TableA A
WHERE NOT EXISTS (SELECT B.Id FROM TableB B WHERE A.Id = B.Id)
GROUP BY A.Id
SELECT DISTINCT Id FROM A WHERE Id NOT IN (SELECT ID FROM B);
SELECT DISTINCT Id FROM A WHERE Id NOT IN(SELECT DISTINCT Id FROM B);
The subquery will get all the IDs in B. The group by...having will get all the unique IDs in A that are also not in B.
select *
from A
where id not in
(
select distinct id
from B
)
group by ID
having count(*) > 1;