IT

두 테이블 간의 차이를 반환하는 SQL 쿼리

lottoking 2020. 5. 19. 08:17
반응형

두 테이블 간의 차이를 반환하는 SQL 쿼리


일부 데이터를 확인하기 위해 SQL Server라는 두 테이블을 비교하려고합니다. 데이터가 하나 또는 다른 두 테이블에서 모든 행을 반환하고 싶습니다. 본질적으로, 나는 모든 불일치를 보여주고 싶다. 이름, 성 및 제품이라는 세 가지 데이터를 확인해야합니다.

나는 SQL을 처음 접했고 내가 찾은 많은 솔루션이 문제를 복잡하게하는 것처럼 보입니다. NULL에 대해 걱정할 필요가 없습니다.

나는 다음과 같이 시도해 보았습니다.

SELECT DISTINCT [First Name], [Last Name], [Product Name] FROM [Temp Test Data]
WHERE ([First Name] NOT IN (SELECT [First Name] 
FROM [Real Data]))

그래도 더 이상 문제가 발생하지 않습니다.

감사!

편집하다:

@treaschf의 답변을 기반으로 다음 쿼리의 변형을 사용하려고했습니다.

SELECT td.[First Name], td.[Last Name], td.[Product Name]
FROM [Temp Test Data] td FULL OUTER JOIN [Data] AS d 
ON td.[First Name] = d.[First Name] AND td.[Last Name] = d.[Last Name] 
WHERE (d.[First Name] = NULL) AND (d.[Last Name] = NULL)

그러나 d에없는 td에 적어도 하나의 행이 있음을 알면 0 결과를 계속 얻습니다.

편집하다:

좋아, 나는 그것을 이해했다고 생각한다. 적어도 몇 분 동안 테스트하면 충분하게 작동하는 것 같습니다.

SELECT [First Name], [Last Name]
FROM [Temp Test Data] AS td
WHERE (NOT EXISTS
        (SELECT [First Name], [Last Name]
         FROM [Data] AS d
         WHERE ([First Name] = td.[First Name]) OR ([Last Name] = td.[Last Name])))

이것은 기본적으로 내 실제 데이터에 없는 테스트 데이터에 무엇이 있는지 알려줍니다 . 내가해야 할 일에 완전히 괜찮습니다.


테이블이 A있고 열 B이 모두 C있는 경우 테이블에 A있지만 레코드에는없는 레코드 가 있습니다 B.

SELECT A.*
FROM A
    LEFT JOIN B ON (A.C = B.C)
WHERE B.C IS NULL

단일 쿼리로 모든 차이점을 얻으려면 다음과 같이 전체 조인을 사용해야합니다.

SELECT A.*, B.*
FROM A
    FULL JOIN B ON (A.C = B.C)
WHERE A.C IS NULL OR B.C IS NULL

이 경우 알아야 할 것은에서 열을 찾을 수 A있지만 B에서 열을 찾을 수 없을 때 레코드가 발견 될 때 B은 NULL 이며, 열에 있거나 B없는 A열은 A의지가 아니라는 것입니다. null 인 경우


(   SELECT * FROM table1
    EXCEPT
    SELECT * FROM table2)  
UNION ALL
(   SELECT * FROM table2
    EXCEPT
    SELECT * FROM table1) 

나는 이것이 대중적인 대답이 아니라는 것을 알고 있지만 더 복잡한 비교가 필요할 때 타사 도구 사용에 @Randy Minder에 동의합니다.

여기 에서이 특정 사례는 쉽고이 경우 이러한 도구가 필요하지 않지만 더 많은 열, 두 서버의 데이터베이스, 더 복잡한 비교 기준 등을 도입하면 쉽게 복잡해질 수 있습니다.

ApexSQL Data Diff 또는 Quest Toad같은 이러한 도구가 많이 있으며 항상 시험 모드에서 작업을 수행 할 수 있습니다.


두 테이블의 모든 차이점을 얻으려면이 SQL 요청과 같이 사용할 수 있습니다.

SELECT 'TABLE1-ONLY' AS SRC, T1.*
FROM (
      SELECT * FROM Table1
      EXCEPT
      SELECT * FROM Table2
      ) AS T1
UNION ALL
SELECT 'TABLE2-ONLY' AS SRC, T2.*
FROM (
      SELECT * FROM Table2
      EXCEPT
      SELECT * FROM Table1
      ) AS T2
;

@erikkallen 답변의 간단한 변형으로 행이있는 테이블을 보여줍니다.

(   SELECT 'table1' as source, * FROM table1
    EXCEPT
    SELECT * FROM table2)  
UNION ALL
(   SELECT 'table2' as source, * FROM table2
    EXCEPT
    SELECT * FROM table1) 

오류가 발생하면

UNION, INTERSECT 또는 EXCEPT 연산자를 사용하여 결합 된 모든 쿼리는 대상 목록에 동일한 수의 표현식이 있어야합니다.

then it may help to add

(   SELECT 'table1' as source, * FROM table1
    EXCEPT
    SELECT 'table1' as source, * FROM table2)  
UNION ALL
(   SELECT 'table2' as source, * FROM table2
    EXCEPT
    SELECT 'table2' as source, * FROM table1) 

If you want to get which column values are different, you could use Entity-Attribute-Value model:

declare @Data1 xml, @Data2 xml

select @Data1 = 
(
    select * 
    from (select * from Test1 except select * from Test2) as a
    for xml raw('Data')
)

select @Data2 = 
(
    select * 
    from (select * from Test2 except select * from Test1) as a
    for xml raw('Data')
)

;with CTE1 as (
    select
        T.C.value('../@ID', 'bigint') as ID,
        T.C.value('local-name(.)', 'nvarchar(128)') as Name,
        T.C.value('.', 'nvarchar(max)') as Value
    from @Data1.nodes('Data/@*') as T(C)    
), CTE2 as (
    select
        T.C.value('../@ID', 'bigint') as ID,
        T.C.value('local-name(.)', 'nvarchar(128)') as Name,
        T.C.value('.', 'nvarchar(max)') as Value
    from @Data2.nodes('Data/@*') as T(C)     
)
select
    isnull(C1.ID, C2.ID) as ID, isnull(C1.Name, C2.Name) as Name, C1.Value as Value1, C2.Value as Value2
from CTE1 as C1
    full outer join CTE2 as C2 on C2.ID = C1.ID and C2.Name = C1.Name
where
not
(
    C1.Value is null and C2.Value is null or
    C1.Value is not null and C2.Value is not null and C1.Value = C2.Value
)

SQL FIDDLE EXAMPLE


Try this :

SELECT 
    [First Name], [Last Name]
FROM 
    [Temp Test Data] AS td EXCEPTION JOIN [Data] AS d ON 
         (d.[First Name] = td.[First Name] OR d.[Last Name] = td.[Last Name])

Much simpler to read.


This will do the trick, similar with Tiago's solution, return "source" table as well.

select [First name], [Last name], max(_tabloc) as _tabloc
from (
  select [First Name], [Last name], 't1' as _tabloc from table1
  union all
  select [First name], [Last name], 't2' as _tabloc from table2
) v
group by [Fist Name], [Last name]
having count(1)=1

result will contain differences between tables, in column _tabloc you will have table reference.


For a simple smoke test where you you're trying to ensure two tables match w/out worrying about column names:

--ensure tables have matching records
Select count (*) from tbl_A
Select count (*) from tbl_B

--create temp table of all records in both tables
Select * into #demo from tbl_A 
Union All
Select * from tbl_B

--Distinct #demo records = Total #demo records/2 = Total tbl_A records = total tbl_B records
Select distinct * from #demo 

You can easily write a store procedure to compare a batch of tables.


I come from the future now you can use except , for example something like this :

-- DB1..Tb1 have values than DB2..Tb1 not have
Select Col1,Col2,Col3 From DB1..Tb1
except
Select Col1,Col2,Col3 From DB2..Tb1
-- Now we change order
-- DB2..Tb1 have values than DB1..Tb1 not have
Select Col1,Col2,Col3 From DB2..Tb1
except
Select Col1,Col2,Col3 From DB1..Tb1

There is a performance issue related with the left join as well as full join with large data.

In my opinion this is the best solution:

select [First Name], count(1) e from (select * from [Temp Test Data] union all select * from [Temp Test Data 2]) a group by [First Name] having e = 1

참고URL : https://stackoverflow.com/questions/2077807/sql-query-to-return-differences-between-two-tables

반응형