Reputation: 24038
I have two tables in my SQL database. I want to check if the Specifier
columns have the exact same data in the exact same order.
OK case, since both tables have the same data in the same order in the Specifier
column:
-- Table1:
RowID Specifier
187 1
188 1
189 2
-- Table2:
RowID Specifier
181 1
182 1
183 2
ERROR case, since the data is different:
-- Table1:
RowID Specifier
187 1
188 2
189 3
-- Table2:
RowID Specifier
181 1
182 2
183 2
ERROR case, since the data is in different order:
-- Table1:
RowID Specifier
187 1
188 1
189 2
-- Table2:
RowID Specifier
181 1
182 2
183 1
ERROR case, since different amount of data:
-- Table1:
RowID Specifier
187 1
188 1
189 2
-- Table2:
RowID Specifier
181 1
182 1
183 2
184 1
I've written the following query, which almost works, and gives correctly an error if one table has a value the other doesn't, but it will incorrectly give no error if only the order is incorect:
IF EXISTS
(SELECT Specifier FROM Table1 EXCEPT SELECT Specifier FROM Table2
UNION ALL
SELECT Specifier FROM Table2 EXCEPT SELECT Specifier FROM Table1)
BEGIN
THROW 99999, 'Mismatching Specifiers between the two tables', 1;
END;
Upvotes: 1
Views: 1039
Reputation: 95561
Seems like it might be easier with
IF EXISTS (SELECT 1
FROM (SELECT ROW_NUMBER() OVER (ORDER BY RowID) AS RN,
Specifier
FROM Table1) T1
FULL OUTER JOIN (SELECT ROW_NUMBER() OVER (ORDER BY RowID) AS RN,
Specifier
FROM Table2) T2 ON T1.RN = T2.RN
AND T1.Specifier = T2.Specifier
HAVING COUNT(CASE WHEN T1.RN IS NULL OR T2.RN IS NULL THEN 1 END) >= 1) ...
Upvotes: 0
Reputation: 1269753
You can use full join
and row_number()
. The following gets the exceptions:
select *
from (select t1.*, row_number() over (order by rowid) as seqnum
from table1 t1
) t1 full join
(select t2.*, row_number() over (order by rowid) as seqnum
from table2 t2
) t2
on t1.seqnum = t2.seqnum and t1.specifier = t2.specifier
where t1.seqnum is null or t2.seqnum is null;
If you simply want a flag:
select (case when count(*) > 1 then 1 else 0 end)
from (select t1.*, row_number() over (order by rowid) as seqnum
from table1 t1
) t1 full join
(select t2.*, row_number() over (order by rowid) as seqnum
from table2 t2
) t2
on t1.seqnum = t2.seqnum and t1.specifier = t2.specifier
where t1.seqnum is null or t2.seqnum is null;
If you care about performance, using the first query with exists
should be faster.
Upvotes: 3