Compare two sql server tables - sql

Can anyone suggest me how to compare two database tables in sql server and return the rows in the second table which are not in the first table. The primary key in both the tables is not the same. For instance, the tables are as follows.
Table1
ID Name DoB
1 John Doe 20/03/2012
2 Joe Bloggs 31/12/2011
Table2
ID Name DoB
11 John Doe 20/03/2012
21 Joe Bloggs 31/12/2011
31 James Anderson 14/04/2010
The sql query should compare only the Name and DoB in both tables and return
31 James Anderson 14/04/2010
Thanks.

Pretty simple, use a LEFT OUTER JOIN to return everything from Table2 even if there isn't a match in Table1, then limit that down to only rows that don't have a match:
SELECT Table2.ID, Table2.Name, Table2.DoB
FROM Table2
LEFT OUTER JOIN Table1 ON Table2.Name = Table1.Name AND Table2.DoB = Table1.DoB
WHERE Table1.ID IS NULL

Look into the use of SQL EXCEPT
SELECT Name, DOB
FROM Table1
EXCEPT
SELECT Name, DOB
FROM Table2
http://msdn.microsoft.com/en-us/library/ms188055.aspx

You want a LEFT OUTER JOIN. http://en.wikipedia.org/wiki/Join_(SQL)#Left_outer_join
This type of JOIN will return all records of the 'left' table (the table in the FROM clause in this example) even if there are no matching records in the joined table.
SELECT Table2.ID, Table2.Name, Table2.DoB
FROM Table2
LEFT OUTER JOIN Table1 ON Table1.Name = Table2.Name AND Table1.DoB = Table2.DoB
WHERE Table1.ID IS NULL
Note that you can substitue LEFT OUTER JOIN for LEFT JOIN. It's a short cut that most DBMSs use.

use CHECKSUM () function in sql server
select T1.* from Table1 T1 join Table2 T2
on CHECKSUM(T1.Name,T1.DOB)!= CHECKSUM(T2.Name,T2.DOB)
Details

This SQL statement compares two tables without having to specify column names.
SELECT 'Table1' AS Tbl, binary_checksum(*) AS chksum, * FROM Table1
WHERE binary_checksum(*) NOT IN (SELECT binary_checksum(*) FROM Table2)
UNION
SELECT 'Table2' AS Tbl, binary_checksum(*) AS chksum, * FROM Table2
WHERE binary_checksum(*) NOT IN (SELECT binary_checksum(*) FROM Table1)
ORDER BY <optional_column_names>, Tbl
The output will display any rows that are different and rows that are in Table1, but not Table2 and vice versa.

Related

Sql query with join on table with ID not match

I have two tables.
Table 1
Id
UpdateId
Name
Table 2
Table1ID
UpdateID
Address
Each time user update, system will insert record to table1. But for table2, system only insert record when there is update in address.
Sample data
Table 1
1,1,name1
1,2,name1
1,3,name1update
1,4,name1update
1,5,name1
1,6,name2
Table 2
1,1,address
1,4,addressupdate
I want to get the result as following
1,1,name1,address
1,2,name1,address
1,3,name1update,address
1,4,name1update,addressupdate
1,5,name1,addressupdate
1,6,name2,addressupdate
How to make use of join condition to achieve as above?
You can use a correlated subquery. Here is standard syntax, but it can be easily adapted to any database:
select t1.*,
(select t2.addressid
from table2 t2
where t2.table1id = t1.id and
t2.updateid <= t1.updateid
order by t2.updateid desc
fetch first 1 row only
) as addressid
from table1 t1;
you can use left join when you want to take all columns from left table t1 even though it doesn't match with the other table with column updateid on t2 table.
select t1.id,t1.updateid,t1.name,t2.address from table1 t1
left join table2 t2
on t2.updateid= t1.updateid
you can read more about joins here

Remove Duplicate Data Based on Three Fields and Two tables

I have two tables that have more than three fields each. There is a group of records that are on both files, the below is a mock example:
Table 1:
ID Name Town State
1 Dave Chicago IL
2 Mark Tea MD
Table 2:
ID Name State Job Married
1 Dave IL Manager Yes
2 Mark MD Driver No
For my purpose duplicates exist if ID, Name, and State are the same. So the above data are duplicates. How do I delete them from one table (I have over 900 duplicates so deleting one by one is not possible)?
delete table1
where ID in(select distinct ID from table1 where ID in (Select ID from table2))
i dont understand which table has duplicates, if you want to delete duplicate data from one table1 then you can use this query
This query will produce a de-duplicated result set:
SELECT Table1.ID,
Table1.NAME,
Table1.Town,
Table1.STATE,
NULL AS Job,
NULL AS Married
FROM Table1
WHERE Table1.ID NOT IN (
SELECT Table1.ID
FROM Table1
INNER JOIN Table2 ON (Table2.STATE = Table1.STATE)
AND (Table2.NAME = Table1.NAME)
AND (Table1.ID = Table2.ID)
)
UNION
SELECT Table2.ID,
Table2.NAME,
NULL AS Town,
Table2.STATE,
Table2.Job,
Table2.Married
FROM Table2
This is the most straightforward way to do it, assuming that you want to delete from Table1. I'm a little rusty with Access SQL syntax, but I believe this works:
DELETE FROM [Table1]
WHERE EXISTS (
SELECT 1
FROM [Table2]
WHERE [Table2].[ID] = [Table1].[ID]
AND [Table2].[Name] = [Table1].[Name]
AND [Table2].[State] = [Table1].[State]
)

Joining two columns but keeping multiple instances in SQL

I am using SQL 2008 and am having a problem.
I have 3 different tables and here is a sample of my code.
SELECT DISTINCT Name Age
FROM Table1
LEFT JOIN Table2
ON Table1.ID = Table2.ID
This returns something like this:
Name Age
tom 12
ben 23
ian 12
I have another query
SELECT Name
FROM Table3
This returns this:
ian 12
ian 12
ian 12
I want to verify that if a name and age are in name from the first query and is in the second query Table3.name it will return something like this:
ian 12
ian 12
ian 12
I have been trying Join and Union on these two columns but so far have been only been able to get it to return. Any suggestions?
ian 12
This might be able to be simplified (need to see your table structures and sample data), but given your queries, a subquery should work for you:
SELECT T3.Name, T3.Age
FROM Table3 T3
JOIN (
SELECT DISTINCT Name, Age
FROM Table1
LEFT JOIN Table2
ON Table1.ID = Table2.ID
) T ON T3.Name = T.Name AND T3.Age = T.Age
SQL Fiddle Demo
First you pronounce your problem - you want to get all records for which combination of Name and Age exists in recordset of distinct Name and Age from join. Then you use power of declarative language and a little of CTE to get your solution:
;with CTE as (
select distinct Name, Age
from Table1 as T1
inner join Table2 as T2 on T2.ID = T1.ID
)
select *
from Table3 as T3
where exists (select * from CTE as C where C.Name = T3.Name and C.Age = T3.Age)
SQL FIDDLE EXAMPLE to fiddle with query

How to extract non-duplicate values in two tables

I have two tables where each one contains columns with numbers. I need to compare columns in both tables and extract the number that does exist in first table, and does not exist in second one. I don't need unique value.
I wrote this query:
SELECT Table1.Numbers, Table1.Name
FROM Table1, Table2
WHERE Table1.Numbers != Table2.numbers
Since I am working on several million records can someone recommend more efficient query which would provide me with identical results?
I would use NOT EXISTS:
SELECT Table1.Numbers, Table1.Name
FROM Table1
WHERE NOT EXISTS(
SELECT 1 FROM Table2
WHERE Table1.Numbers=Table2.Numbers
)
Other approaches:
Should I use NOT IN, OUTER APPLY, LEFT OUTER JOIN, EXCEPT, or NOT EXISTS?
You can do this easily by checking for the existance on the number in Table2.
SELECT T1.Numbers
,T1.Name
FROM Table1 T1
WHERE NOT EXISTS (SELECT 1 FROM Table2 T2 WHERE T2.Numbers = T1.Numbers)
Try this (assuming that your Numbers column are not nullable)
SELECT T1.Numbers, T1.Name
FROM Table1 AS T1
LEFT JOIN Table2 AS T2 ON T1.Numbers = T2.Numbers
WHERE T2.Numbers IS NULL;
SELECT
Table1.Numbers, Table1.Name
FROM
Table1, Table2
GROUP BY
Table1, Table2
HAVING
COUNT(*) > 1

sql simple 3 table join using same table?

I have two tables:
Table 1
id, name1
Table 2
id, name2a, name2b
Table 2's column names name2a, and name2b are references to table 1's id. I need to create a query that pulls both the names out of table 1 based on the id's used in Table 2.
Therefore, if Table one contained:
1 Peter
2 Paul
And Table 2 contained:
1 1 2
2 2 2
Then a select statement should give me:
Peter Paul
Paul Paul
I've gone around the bend trying to build this SQL and the best I came up with was:
SELECT table1.name AS 'name', table1.name AS 'Other name'
FROM table1, table2
WHERE table1.id = table2.name2a
Which only gives me the name2a column correctly.
Any help appreciated! I guess I need to do a join, but I'm really struggling...
Start with your 2nd table and join TWICE to table 1 (different aliases respectively), then get the name field from each aliased Table1 entry.
select
T2.ID,
TJ1.Name1 as FirstName,
TJ2.Name1 as SecondName
from
Table2 t2
join Table1 TJ1
on t2.Name2a = TJ1.ID
join Table1 TJ2
on t2.Name2b = TJ2.ID
select foo.*, t1.x, t2.y
join t1 on t1.id = foo.a
join t1 as t2 on t2.id = foo.b
If there's a chance that col a or col b is null, use a left join.
Have you tried using an INNER JOIN?
SELECT table1.name AS 'name', table1.name AS 'Other name'
FROM table1 INNER JOIN table2 ON table1.id = table2.name2a;
Sorry if I'm no help, not that great at SQL myself hehe.
Your problem is that you need to reference table1 twice: once for the plain table1.name and again to look up what table2 is pointing at. You can join one table in multiple times if you give them aliases:
SELECT t1.name1, o.name1
FROM table1 t1
JOIN table2 t2 ON t1.id = t2.name2a
JOIN table1 o ON t2.name2b = o.id -- And JOIN back to table1 to get the name1