Querying Two Tables For Duplicate Values - sql

I have a stored procedure which moves (or ought to) records from one table to another. However I now want to create a procedure that checks the data in 'TableA' against the data in 'TableB'
SELECT A.Num, B.Num
FROM TableA AS A
LEFT JOIN TableB AS B ON A.Num = B.Num
WHERE B.Num IS NULL
Basically, I want to pull out any number which isn't in 'TableB' but is in 'TableA', is a LEFT JOIN the way to do this? I have been unsuccessful in locating missing files so far, and I have removed some to form a test case.

You can use a not exists
SELECT *
FROM TableA A
WHERE NOT EXISTS (SELECT *
FROM TableB B
WHERE A.NUM = B.NUM);
or not in:
SELECT *
FROM TableA A
WHERE A.NUM not in (SELECT B.NUM
FROM TableB B);

SELECT Num from TableA
EXCEPT
SELECT Num from TableB

select * from tableA
where id not in (select id from tableB)
or
select * from tableA a
left join tableB b on a.id = b.id
where b.id is null

select * from tableA
where id in (select id from tableB);

Finding duplicates between two table
select table1.column_name, count(*) from table_name table1
inner join table_name table2
ON table1.coumn_name = table2.column_name;
ex:
SELECT u.username FROM users u
INNER JOIN src_users ud
ON u.username = ud.username;
Finding duplicates in single table
select username, count(*) from users group by username having count(*) >1;

Related

Compare two tables via the three tables SQL

I plan to compare two tables via the three table. my query is as the following
Select count(*)
from tableA a
join tableB b
on a.A_ID =b.A_ID
full join tableC c
on c.B_ID=b.B_ID
where a.A_ID is null or c.B_ID is null
if the count is zore, then the tableA and TableC match, otherwise, these two tables do not match
It takes a long time to run the query. Do we have a way to compare tableA and tableC fast?
Question: How to compare tableA and tableC?
You don't need a FULL JOIN here, you can just join the first two tables, then EXCEPT the third.
SELECT COUNT(*)
FROM (
SELECT b.B_ID, a.A_Name
FROM tableA a
JOIN tableB b ON a.A_ID = b.A_ID
EXCEPT
SELECT c.B_ID, c.B_Name
FROM tableC c
) t;
Note that EXCEPT implies DISTINCT so if you want the number of rows extra in table_A then you need to use WHERE NOT EXISTS
SELECT b.B_ID, a.A_Name
FROM tableA a
JOIN tableB b ON a.A_ID = b.A_ID
WHERE NOT EXISTS (SELECT 1
FROM tableC c
WHERE c.B_ID = b.B_ID AND c.B_Name = a.A_Name
);
If you want to find rows that are in one table but not the other you can use the EXCEPT union in standard SQL
-- Show in A not in B
SELECT * FROM TableA EXCEPT SELECT * FROM TableB
-- Show in A not in C
SELECT * FROM TableA EXCEPT SELECT * FROM TableC
-- Show in B not in A
SELECT * FROM TableB EXCEPT SELECT * FROM TableA
-- Show in B not in C
SELECT * FROM TableB EXCEPT SELECT * FROM TableC
-- Show in C not in A
SELECT * FROM TableC EXCEPT SELECT * FROM TableA
-- Show in C not in B
SELECT * FROM TableC EXCEPT SELECT * FROM TableB

SQL query to select from one table based on a column value in other table

I have two tables and I want to select all values from "TABLE A" that have a different value in a column from "TABLE B".
I tried this
SELECT A.* FROM tableA A
left join tableB B ON A.id = B.id WHERE B.column <> 1;
But this just return the value that I want to ignore.
SELECT A.*
FROM tableA A
INNER JOIN tableB B
ON A.id = B.id
WHERE B.column != 1;
or
SELECT A.* FROM tableA A WHERE A.Id NOT IN (SELECT B.Id FROM tableB B WHERE B.column != 1)
Depends on your SQL you can use <> or !=
I would suggest not exists:
SELECT A.*
FROM tableA A
WHERE NOT EXISTS (SELECT 1 FROM tableB B WHERE A.id = B.id AND B.column = 1);
Using a JOIN can result in duplicated rows, if more than one row in B matches the JOIN condition.

Join tables that might not have records

I have two tables, tableA which has a list of records and tableB which has restrictions (if any). How can I join the tables that will essentially be an inner join if there are records in tableB or no join if tableB is empty?
ie:
tableA
id | name
1 | val1
2 | val2
tableB (with restrictions)
id | name | userID
1 | val1 | 123
OR tableB (no restrictions)
id | name | userID
is this possible? My attempt below:
SELECT a.*
FROM tableA a
INNER JOIN (CASE WHEN select 1 from tableB = 1 THEN tableB ELSE tableA END) b
ON a.id = b.id
where userID = XXX
EDIT: There is a check on tableB
Just use a left join
SELECT a.*
FROM tableA a
LEFT JOIN tableB b = ON a.id = b.id and b.userid = xxx
I'm not seeing any complexity beyond that at present - given the simplicity of the statement in the original question, I am wondering if you are putting WHERE predicates against the table B - if you are, they need to be in the ON clause of the join
Edited to include your where clause moved.
For empty rows, u can use same query for both restrictions.
I guess you are usign SQL server
Use left join to pull rows if table b is blank
select a.id,a.name
from tableA a left join tableB on a.id = b.id
Demo:
declare #tableA table (id int, name varchar(10))
insert into #tableA
select 1, 'name'
union all
select 2,'name1'
union all
select 3,'name2'
declare #tableb table (id int, name varchar(10))
select a.id,a.name
from #tableA a left join #tableb b on a.id = b.id
this will pull all records from tableA if tableB is empty and only matching records if it is not:
select a.id, a.name
from tableA a
join tableB on a.id = b.id
where exists (select 1 from tableB)
union all
select a.id, a.name
from tableA a
where not exists (select 1 from tableB)

XOR JOIN in SQL

I have the following tables
Table A
ID "Other Columns"
1
2
3
Table B
ID "Other Columns"
3
4
5
What is the efficient way to return the below result?
Result
ID "Other Columns"
1
2
4
5
A full outer join should work, and only go through each table once. They can be tricky, so test carefully!
SELECT
isnull(A.ID, B.ID) ID
,"Other columns" -- Handle nulls properly!
from TableA A
full outer joing TableB B
on B.ID = A.ID
where not (A.ID is not null
and B.ID is not null)
You want to use left and right join and union them
Select TableA.ID as 'ID','Other Colums'
FROM TableA Left join TableB
ON TableA.ID=TableB.ID
WHERE TableB.ID IS NULL
UNION
Select TableB.ID as 'ID','Other Colums'
FROM TableA Right join TableB
ON TableA.ID=TableB.ID
WHERE TableA.ID IS NULL
You can try like this
SELECT
COALESCE(a.id, b.id),
OtherColumns
FROM #tablea a
FULL JOIN #tableb b
ON a.id = b.id
WHERE a.id IS NULL
OR b.id IS NULL
You can do this with a UNION ALL using a LEFT JOIN to determine if the ID is not in the other table. Keep in mind that the column count and datatypes between the two tables must match up:
Select A.Id, A.OtherColumns
From TableA A
Left Join TableB B On A.Id = B.Id
Where B.Id Is Null
Union All
Select B.Id, B.OtherColumns
From TableB B
Left Join TableA A On A.Id = B.Id
Where A.Id Is Null
Not quite sure what you need with the "Other columns", but you could use EXCEPT:
Select ID from TableA
EXCEPT
Select ID from TableB
If you need Other columns from TableA you could use:
Select ID, OtherColumn1, OtherColumn2 from TableA
where ID not in (select ID from TableB)
(as long as ID cannot be null in TableB)
I broke down each part to be clearer!
select *
into #temp
from
TabA Full outer join TabB
on TabA.ColNameA = TabB.ColNameB
select *
into #temp2
from #temp
where (ColNameA is Null Or ColNameB is null)
select ColNameA from #temp2
where ColNameA Is not null
union
select ColNameB from #temp2
where ColNameB Is not null

sql - multiple layers of correlated subqueries

I have table A, B and C
I want to return all entries in table A that do not exist in table B and of that list do not exist in table C.
select * from table_A as a
where not exists (select 1 from table_B as b
where a.id = b.id)
this gives me the first result of entries in A that are not in B. But now I want only those entries of this result that are also not in C.
I tried flavours of:
select * from table_A as a
where not exists (select 1 from table_B as b
where a.id = b.id)
AND
where not exists (select 1 from table_C as c
where a.id = c.id)
But that isnt the correct logic. If there is a way to store the results from the first query and then select * from that result that are not existent in table C. But I'm not sure how to do that. I appreciate the help.
Try this:
select * from (
select a.*, b.id as b_id, c.id as c_id
from table_A as a
left outer join table_B as b on a.id = b.id
left outer join table_C as c on c.id = a.id
) T
where b_id is null
and c_id is null
Another implementation is this:
select a1.*
from table_A as a1
inner join (
select a.id from table_A
except
select b.id from table_B
except
select c.id from table_c
) as a2 on a1.id = a2.id
Note the restrictions on the form of the sub-query as described here. The second implementation, by most succinctly and clearly describing the desired operation to SQL Server, is likely to be the most efficient.
You have two WHERE clauses in (the external part of) your second query. That is not valid SQL. If you remove it, it should work as expected:
select * from table_A as a
where not exists (select 1 from table_B as b
where a.id = b.id)
AND
not exists (select 1 from table_C as c -- WHERE removed
where a.id = c.id) ;
Tested in SQL-Fiddle (thnx #Alexander)
how about using LEFT JOIN
SELECT a.*
FROM TableA a
LEFT JOIN TableB b
ON a.ID = b.ID
LEFT JOIN TableC c
ON a.ID = c.ID
WHERE b.ID IS NULL AND
c.ID IS NULL
SQLFiddle Demo
One more option with NOT EXISTS operator
SELECT *
FROM dbo.test71 a
WHERE NOT EXISTS(
SELECT 1
FROM (SELECT b.ID
FROM dbo.test72 b
UNION ALL
SELECT c.ID
FROM dbo.test73 c) x
WHERE a.ID = x.ID
)
Demo on SQLFiddle
Option from #ypercube.Thank for the present;)
SELECT *
FROM dbo.test71 a
WHERE NOT EXISTS(
SELECT 1
FROM dbo.test72 b
WHERE a.ID = b.ID
UNION ALL
SELECT 1
FROM dbo.test73 c
WHERE a.ID = c.ID
);
Demo on SQLFiddle
I do not like "not exists" but if for some reason it seems to be more logical to you; then you can use a alias for your first query. Subsequently, you can re apply another "not exists" clause. Something like:
SELECT * FROM
( select * from tableA as a
where not exists (select 1 from tableB as b
where a.id = b.id) )
AS A_NOT_IN_B
WHERE NOT EXISTS (
SELECT 1 FROM tableC as c
WHERE c.id = A_NOT_IN_B.id
)