2014-02-10 2 views
3

저는 데이터베이스로 SQL Server 2008 (v10.0 SP3)을 사용하고 있습니다.두 구조적으로 비슷한 테이블을 비교하고 SQL Server에서 다른 값의 열 이름과 값만 반환하는 방법은 무엇입니까?

두 개의 거의 동일한 테이블 구조를 현명하게 비교하고 일치하지 않는 열 이름과 값만 반환하는 방법을 찾으려고합니다.

두 개의 테이블이 있습니다.

표 A에는 약 260 개의 열과 각 레코드에 대한 고유 한 식별자가 있습니다. 그것은 다른 서버에서 볼 수 있습니다.

표 B은 삽입 날짜 열과 작업 열이 추가 된 구조의 표 A 사본입니다.

IF OBJECT_ID('tempdb..#TableA') IS NOT NULL 
    DROP TABLE #TableA 
IF OBJECT_ID('tempdb..#TableB') IS NOT NULL 
    DROP TABLE #TableB 

CREATE TABLE #TableA (
UniqueID INT,[Name] CHAR(3),[Address] CHAR(15), 
HairColor CHAR(6),ImportDate DATETIME 
) 

CREATE TABLE #TableB (
UniqueID INT,[Name] CHAR(3),[Address] CHAR(15), 
HairColor CHAR(6),ImportDate DATETIME, 
AuditDate DATETIME,[Action] CHAR(10) 
) 

INSERT INTO #TableA 
VALUES (1,'Joe','1 Main St.','Brown','12/1/2013') 

INSERT INTO #TableA 
VALUES (2,'Jen','1 Main St.','Red','12/1/2013') 

INSERT INTO #TableB 
VALUES (2,'Jen','1 Main St.','Blonde','10/1/2013','12/1/2013','CHANGE') 

INSERT INTO #TableB 
VALUES (2,'Jen','1 Baker St.','Blonde','4/1/2010','10/1/2013','CHANGE') 

INSERT INTO #TableB 
VALUES (2,'Jen','4 Deer Ave.','Black','6/1/2004','4/1/2010','CHANGE') 

SELECT * FROM #TableA AS ta 

SELECT * FROM #TableB AS tb 

표 A

╔══════════╦══════╦════════════╦═══════════╦════════════╗ 
║ UniqueID ║ Name ║ Address ║ HairColor ║ ImportDate ║ 
╠══════════╬══════╬════════════╬═══════════╬════════════╣ 
║  1 ║ Joe ║ 1 Main St. ║ Brown  ║ 12/1/2013 ║ 
║  2 ║ Jen ║ 1 Main St. ║ Red  ║ 12/1/2013 ║ 
╚══════════╩══════╩════════════╩═══════════╩════════════╝ 

표 B

╔══════════╦══════╦═════════════╦═══════════╦════════════╦═══════════╦════════╗ 
║ UniqueID ║ Name ║ Address ║ HairColor ║ ImportDate ║ AuditDate ║ Action ║ 
╠══════════╬══════╬═════════════╬═══════════╬════════════╬═══════════╬════════╣ 
║  2 ║ Jen ║ 1 Main St. ║ Blonde ║ 10/1/2013 ║ 12/1/2013 ║ CHANGE ║ 
║  2 ║ Jen ║ 1 Baker St. ║ Blonde ║ 4/1/2010 ║ 10/1/2013 ║ CHANGE ║ 
║  2 ║ Jen ║ 4 Deer Ave. ║ Black  ║ 6/1/2004 ║ 4/1/2010 ║ CHANGE ║ 
╚══════════╩══════╩═════════════╩═══════════╩════════════╩═══════════╩════════╝ 

표 A는 잘립니다 매월 다시로드하지만이 완료되기 전에, 새로운 데이터를 비교오고 in 표 A (new A) 및 이미 표 A (old A)에있는 데이터가 발생합니다.

새로운 A가 오래된에있는 행을 포함하지 않는 경우

나는 액션으로 insertdateDELETED표 B에 행 구를 삽입합니다.

새로운 A가 오래된에없는 행을 포함하는 경우

나는 액션으로 insertdateADDED표 B에 행 새를 삽입합니다.

새로운 A는 오래된 일치하지 않는 열이있는 행이 포함되어있는 경우

나는 액션으로 insertdateCHANGE표 B에 행 구를 삽입합니다.

위에서 볼 수 있듯이 표 A의 고유 레코드에 대한 원본 데이터가 월 단위로 변경 될 수 있으므로 표 B는 표 A와 동일한 고유 식별자를 가진 여러 행을 가질 수 있습니다.

이제 추가 및 삭제가보고하기 쉽습니다. 내가 어려움을 겪고있는 것은 변화를보고하는 것입니다. 260 일반적인 행으로 내가 표 A에 관련 컬럼과 일치하지 않는 표 B에 열을 선택할 수 있도록하고 싶습니다, 내가 가진 테이블 반환 함수를 만드는 방법에 대한 생각 TableA.UniqueID = TableB.UniqueID

에 합류 왼쪽 이 같은 표 A에서 입력 UniqueID를 사용하여 출력 뭔가 :

╔══════════╦════════════╦═════════════╦════════════╦═══════════╦════════╗ 
║ UniqueID ║ ColumnName ║ Value ║ ImportDate ║ AuditDate ║ Action ║ 
╠══════════╬════════════╬═════════════╬════════════╬═══════════╬════════╣ 
║  2 ║ HairColor ║ Blonde  ║ 10/1/2013 ║ 12/1/2013 ║ CHANGE ║ 
║  2 ║ Address ║ 1 Baker St. ║ 4/1/2010 ║ 10/1/2013 ║ CHANGE ║ 
║  2 ║ HairColor ║ Blonde  ║ 4/1/2010 ║ 10/1/2013 ║ CHANGE ║ 
║  2 ║ Address ║ 4 Deer Ave. ║ 6/1/2004 ║ 4/1/2010 ║ CHANGE ║ 
║  2 ║ HairColor ║ Black  ║ 6/1/2004 ║ 4/1/2010 ║ CHANGE ║ 
╚══════════╩════════════╩═════════════╩════════════╩═══════════╩════════╝ 

나는 그것을 할 방법 다만 확실하지 않다.

내 머리가 작동하지 않는 곳입니다. ORDINAL_POSITION을 INFORMATION_SCHEMA.COLUMNS에서 사용할 수 있습니까?당신의 Visual Studio Premium 또는 궁극이 있다면 당신은 모든 열이를 시도 할 수

SELECT a.ORDINAL_POSITION,a.COLUMN_NAME 
FROM INFORMATION_SCHEMA.COLUMNS AS a 
JOIN INFORMATION_SCHEMA.COLUMNS AS b ON a.COLUMN_NAME = b.COLUMN_NAME 
WHERE a.TABLE_NAME = 'TableA' AND a.TABLE_SCHEMA='dbo' 
AND b.TABLE_NAME = 'TableB' AND b.TABLE_SCHEMA='dbo' 

답변

0

같은 소리가 UNPIVOT입니다. MSDN에서 : 나는 유형 간의 충돌을 해결하기 위해 nvarchar(255)에 값을 던져

SELECT UniqueID, ColumnName, Value, ImportDate, AuditDate, Action 
FROM 
(
    SELECT 
     TableA.UniqueID, 
     CAST((CASE WHEN ISNULL(TableB.Address, '') <> ISNULL(TableA.Address, '') 
       THEN ISNULL(TableB.Address, '') 
       ELSE NULL END) AS nvarchar(255)) 
     AS Address, 
     CAST((CASE WHEN ISNULL(TableB.HairColor, '') <> ISNULL(TableA.HairColor, '') 
       THEN ISNULL(TableB.HairColor, '') 
       ELSE NULL END) AS nvarchar(255)) 
     AS HairColor, 
     TableB.ImportDate, 
     TableB.AuditDate, 
     TableB.Action 
    FROM TableA INNER JOIN TableB ON TableB.UniqueID = TableA.UniqueID 
) AS p 
UNPIVOT 
(
    Value FOR ColumnName in (Address, HairColor) 
) AS up 
WHERE Value IS NOT NULL 

참고 :

Using PIVOT and UNPIVOT 여기에 귀하의 질문에 가능한 솔루션입니다. 더 적절한 것으로 조정해야 할 수도 있습니다.

또한 한눈에, 생성 된 결과가 가져 오기 및 감사 날짜를 기반으로하는 일부 정제가 필요할 수 있다고 생각합니다. 그러나 그것은 또 다른 주제입니다. 또한 LEFT JOIN이이 경우 나에게 이해가되지 않았기 때문에 INNER JOIN을 사용하여 종료되었습니다. 어쩌면 내가 뭔가를 놓친 것 같아.

이렇게 말하면서, 이것은 당신이 찾고있는 결과를 얻어야 만합니다.

+0

필요한 경우 더 많은 열을 추가 할 수 있습니다. 그것들을'UNPIVOT' 표현식에 추가하는 것을 기억하십시오. – Manny

+0

안녕하세요, Manny 님, 의견을 보내 주셔서 감사합니다. "열 유형"HairColor "가 UNPIVOT 목록에 지정된 다른 열 유형과 충돌하는 이유는 무엇입니까? 오류 – Mike

+0

해당 열을 모든 필드를 포함하는 적절한 것으로 변환 해보십시오. 아마'varchar (255)'? – Manny

0

...

SELECT a.UniqueID,'HairColour' [ColumnName],b.HairColour [Value],...,'CHANGE' [Action] FROM Tableb b 
INNER JOIN Tablea a ON 
    a.UniqueID = b.uniqueID 
WHERE a.HairColor <> b.HairColor 

UNION 

    SELECT a.UniqueID,'Address' [ColumnName],b.Address [Value],...,'CHANGE' [Action] FROM Tableb b 
INNER JOIN Tablea a ON 
    a.UniqueID = b.uniqueID 
WHERE a.Address <> b.Address 

etc... 
0

, 당신은이 목적을 위해 데이터베이스 프로젝트를 비교하여 스키마를 사용할 수 있습니다. 꽤 정교하며 소스 및/또는 목표의 차이점에 대한 DDL을 생성 할 수도 있습니다. 필요한 경우 데이터를 비교할 수도 있습니다. 나는 과거에 많은 프로젝트에서 그것을 사용 해왔다.

MSDN : Compare and Synchronize Database Schemas.

+0

정보 주셔서 감사합니다.하지만 VS에 액세스 할 수 없습니다. – Mike

관련 문제