2010-03-12 4 views
3

Voici le scénario:Comment puis-je comparer les lignes de deux tables comportant des clés primaires composites?

J'ai 2 tables avec des données, l'une est la version 2009 et l'autre est la version 2010. La clé primaire pour chacune des tables est une clé composite. Je sais qu'il y a un nombre différent de rangées dans chacune d'elles et j'ai besoin de trouver les différences.

En règle générale, dans la configuration de la clé primaire "normale", je rechercherais simplement les valeurs de clé primaire NOT IN dans la liste des clés primaires de l'autre table. Mais je ne sais pas comment le faire avec une clé primaire composite (ou même si c'est possible). Alors, comment puis-je comparer les lignes de ces deux tables?


EDIT: Plus précisément, j'essaie de trouver la différence entre les tables, plutôt que les lignes communes

Répondre

10

juste faire une jointure externe avec condition basée sur clés composites:

select t09.*, t10.* 
from table2009 as t09 
    full outer join table2010 as t10 
    on t09.k1 = t10.k1 and t09.k2 = t10.k2 and ... 

Si vous souhaitez voir uniquement les lignes inégalées (la différence) en résultat se t, puis filtre dans la clause where:

where t09.k1 is null or t10.k1 is null 
+0

a ajouté que la « différence » vous parliez; Toutefois, vous souhaiterez peut-être rechercher uniquement un côté (par exemple, les lignes de 2010 qui n'apparaissent pas dans la table 2009). La jointure gauche fera l'affaire. – incarnate

1

select * from [table2009] right outer join [table2010] on [table2009].[PK1] = [table2010].[PK2] and [table2009].[PK2] = [table2010].[PK2] where [table2009].[PK1] is null

0

Vous pouvez prendre une somme de contrôle des colonnes composites et à comparer entre les tables, afin de rendre le rejoindre un peu plus compact.

select ... 
-------------------------- 
--or left outer join etc. 
-------------------------- 
from a inner join b 
on checksum(a.col1, a.col2, a.col3) = checksum(b.col1, b.col2, b.col3) 
0

En supposant que vous ne voulez pas comparer toutes les colonnes.

DECLARE @Table2009 TABLE 
( Year INT 
,Counter INT IDENTITY (-2147483647 , 1) 
,OtherData CHAR(1) 
,PRIMARY KEY (Year, Counter) 
); 
DECLARE @Table2010 TABLE 
( Year INT 
,Counter INT IDENTITY (-2147483647 , 1) 
,OtherData CHAR(1) 
,PRIMARY KEY (Year, Counter) 
); 
SELECT 'NOT IN Table2010' 
    ,Table2009.Year 
    ,Table2009.Counter 
FROM @Table2009 Table2009 
LEFT JOIN @Table2010 Table2010 ON Table2009.Year = Table2010.Year 
      AND Table2009.Counter = Table2010.Counter 
WHERE Table2010.Year IS NULL 
UNION 
SELECT 'NOT IN Table2010' 
    ,Table2009.Year 
    ,Table2009.Counter 
FROM @Table2010 Table2010 
LEFT JOIN @Table2009 Table2009 ON Table2010.Year = Table2009.Year 
      AND Table2010.Counter = Table2009.Counter 
WHERE Table2009.Year IS NULL; 
0

Quelques données à tester:

CREATE TABLE Tbl_1 (
    ID1 integer NOT NULL 
, ID2 int NOT NULL 
, SomeData varchar(20) 
); 
ALTER TABLE Tbl_1 ADD 
    CONSTRAINT pk_tbl_1 PRIMARY KEY (ID1, ID2); 

CREATE TABLE Tbl_2 (
    ID1 integer NOT NULL 
, ID2 int NOT NULL 
, SomeData varchar(20) 
); 
ALTER TABLE Tbl_2 ADD 
    CONSTRAINT pk_tbl_2 PRIMARY KEY (ID1, ID2); 

INSERT INTO Tbl_1 
(ID1, ID2, SomeData) 
VALUES 
    (1, 1, '1_1') 
, (2, 2, '2_2') 
, (3, 3, '3_3') 
; 

INSERT INTO Tbl_2 
(ID1, ID2, SomeData) 
VALUES 
    (1, 1, '1_1') 
, (3, 3, '3_3') 
, (4, 4, '4_4') 
; 

...

-- All rows that are in the first table, 
-- but not in the second one 
SELECT 
    a.ID1 AS t1_ID1 
    ,a.ID2 AS t1_ID2 
    ,a.SomeData AS t1_SomeData 
    ,b.ID1 AS t2_ID1 
    ,b.ID2 AS t2_ID2 
    ,b.SomeData AS t2_SomeData 
FROM Tbl_1 as a 
LEFT JOIN Tbl_2 as b ON b.ID1 = a.ID1 AND b.ID2 = a.ID2 
WHERE b.ID1 IS NULL; 

Retours:

t1_ID1 t1_ID2 t1_SomeData t2_ID1 t2_ID2 t2_SomeData 
------- -------- ------------- -------- -------- ----------- 
2  2  2_2   NULL  NULL  NULL 

...

-- All rows that are in the second table, 
-- but not in the first one 
SELECT 
    a.ID1 AS t1_ID1 
    ,a.ID2 AS t1_ID2 
    ,a.SomeData AS t1_SomeData 
    ,b.ID1 AS t2_ID1 
    ,b.ID2 AS t2_ID2 
    ,b.SomeData AS t2_SomeData 
FROM Tbl_1 as a 
RIGHT JOIN Tbl_2 as b ON b.ID1 = a.ID1 AND b.ID2 = a.ID2 
WHERE a.ID1 IS NULL; 

Retours:

t1_ID1 t1_ID2 t1_SomeData t2_ID1 t2_ID2 t2_SomeData 
------- ------- ------------- -------- ------- ------------ 
NULL NULL NULL   4  4  4_4 

...

-- Common to both tables 
SELECT 
    a.ID1 AS t1_ID1 
    ,a.ID2 AS t1_ID2 
    ,a.SomeData AS t1_SomeData 
    ,b.ID1 AS t2_ID1 
    ,b.ID2 AS t2_ID2 
    ,b.SomeData AS t2_SomeData 
FROM Tbl_1 as a 
JOIN Tbl_2 as b ON b.ID1 = a.ID1 AND b.ID2 = a.ID2; 

Retours

t1_ID1  t1_ID2  t1_SomeData t2_ID1  t2_ID2  t2_SomeData 
----------- ----------- ------------- ----------- ----------- ------------ 
1   1   1_1   1   1   1_1 
3   3   3_3   3   3   3_3 
0

j'ai utilisé comme ça! avec juste une jointure externe gauche.

et je l'ai utilisé un autre champ pour vérifier l'état

SELECT * FROM actas LEFT OUTER JOIN acta_detalle_proceso on actas.id = acta_detalle_proceso.id 
and actas.tipo_acta_id = acta_detalle_proceso.tipo_acta_id and acta_detalle_proceso.estado = 1 
WHERE acta_detalle_proceso.id IS NULL and acta_detalle_proceso.tipo_acta_id IS NULL ; 
0
-- Entity in Tbl_1 only 
SELECT ID1, ID2 
    FROM Tbl_1 
EXCEPT 
SELECT ID1, ID2 
    FROM Tbl_2; 

-- Entity in Tbl_2 only 
SELECT ID1, ID2 
    FROM Tbl_2 
EXCEPT 
SELECT ID1, ID2 
    FROM Tbl_1; 

-- Entity in both tables 
-- with same attribute values 
SELECT ID1, ID2, SomeData 
    FROM Tbl_1 
INTERSECT 
SELECT ID1, ID2, SomeData 
    FROM Tbl_2; 

-- Entity in both tables but 
-- with different attribute values 
SELECT DISTINCT T1.ID1, T1.ID2, 
     T1.SomeData AS Tbl_1__SomeData, 
     T2.SomeData AS Tbl_2__SomeData 
    FROM Tbl_1 AS T1, Tbl_2 AS T2 
WHERE T1.ID1 = T1.ID1 
     AND T1.ID2 = T2.ID2 
     AND T1.SomeData <> T2.SomeData; 
Questions connexes