2017-02-23 6 views
3

Ich habe folgende (vereinfachte) Lage in zwei Datenbanken:passenden Gruppen von Reihen in zwei Datenbanken

ID  Prog  T   Qt 
|---------|--------|---------|---------| 
| a  | 1 | N  | 100 | 
| b  | 1 | Y  | 10 | 
| b  | 2 | N  | 90 | 
| c  | 1 | N  | 25 | 
| c  | 2 | Y  | 25 | 
| c  | 3 | Y  | 25 | 
| c  | 4 | Y  | 25 | 
|---------|--------|---------|---------| 

ID  Prog  T   Qt 
|---------|--------|---------|---------| 
| 1  | 1 | Y  | 10 | 
| 1  | 2 | N  | 90 | 
| 2  | 1 | Y  | 100 | 
| 3  | 1 | Y  | 100 | 
| 4  | 1 | Y  | 50 | 
| 4  | 2 | Y  | 25 | 
| 4  | 3 | Y  | 25 |  
|---------|--------|---------|---------| 

Ich brauche Gruppen von Zeilen zu vergleichen (primäre Schlüssel-ID und Prog) , um herauszufinden, welche Gruppen von Zeilen die gleiche Kombination von Faktoren darstellen (ohne ID zu berücksichtigen).

Im obigen Beispiel haben die ID "b" in der ersten Tabelle und die ID "1" in der zweiten die gleiche Kombination von Werten für Prog, T und Qt, während niemand sonst als exakt gleich angesehen werden kann 2 dbs (während ID "2" und "3" in der zweiten Tabelle gleich sind, bin ich nicht daran interessiert, in derselben db zu vergleichen).

Ich hoffe, ich habe alles erklärt.

+0

@iamdave mein Befehl von SQL nicht so gut ist, wie es etwas mehr sein sollte als ein paar SELECT-Anweisung zu versuchen. Ich denke, ich sollte eine Funktion oder eine gespeicherte Prozedur verwenden, um mögliche Ergebnisse über alle IDs in der ersten Tabelle zu holen, anstatt auf eine Reihe von SELECT * FROM ... JOIN ... ON ... WHERE zurückgreifen zu müssen. .. Die Wahrheit ist, ich habe etwas auf dieser Seite und anderswo durchsucht, aber niemand scheint etwas über das Thema gesagt zu haben. Es gibt 2 Dutzend Werte, die passen, also war ich auf der Suche nach etwas Ordentlichem und Elegantem – MaZe

Antwort

3

Eine Verknüpfung und Aggregation sollte zu diesem Zweck arbeiten:

select t1.id, t2.id 
from (select t1.*, count(*) over (partition by id) as cnt 
     from t1 
    ) t1 join 
    (select t2.*, count(*) over (partition by id) as cnt 
     from t2 
    ) t2 
    on t1.prog = t2.prog and t1.T = t2.T and t1.Qt = t2.Qt and t1.cnt = t2.cnt 
group by t1.id, t2.id, t1.cnt 
having count(*) = t1.cnt; 

Dies ist ein wenig kompliziert ist. Die Unterabfragen zählen die Anzahl der Zeilen für jede ID in jeder Tabelle. Die on-Klausel erhält Übereinstimmungen zwischen den drei Spalten - und überprüft, ob die IDs die gleiche Anzahl haben. Die Zeilen group by und having erhalten dann Zeilen, wobei die Anzahl der übereinstimmenden Zeilen die Gesamtzahl der Zeilen ist.

+0

Danke Gordon, du hast Recht: Ich war ziemlich sicher, dass ich für jede Kombination der ersten Tabelle nur die Kombinationen mit der gleichen Anzahl von Zeilen überprüfen sollte. Ich werde es mir ansehen. Wie ich an Wes H schrieb, würde ich gerne etwas eleganteres finden, als wenn ich auf zwei Dutzend Werte setze, aber wenn SQL nichts Besseres hat, werde ich mit beiden gehen! – MaZe

+1

@MaZe. . . In anderen Datenbanken verwenden Sie 'listagg()', 'group_concat()' oder etwas Ähnliches. Obwohl Sie dies in SQL Server * tun können, ist es wahrscheinlich noch weniger elegant als diese Lösung. –

1

Verbinden Sie die beiden Tabellen mit den Bedingungen, die Sie abgleichen möchten. Die Ergebnisse werden die Werte sein, die zwischen ihnen übereinstimmen.

CREATE TABLE a (ID CHAR(1), Prog INT, T CHAR(1), Qt INT); 
CREATE TABLE b (ID int, Prog INT, T CHAR(1), Qt INT); 

    INSERT INTO dbo.a 
      (ID ,Prog ,T ,Qt) 
    VALUES ('a',1,'N',100), ('b',1,'Y',10), ('b',2,'N',90),('c',1,'N',25),('c',2,'Y',25),('c',3,'Y',25),('c',4,'Y',25) 
    INSERT INTO dbo.b 
      (ID ,Prog ,T ,Qt) 
    VALUES (1,1,'Y',10),(1,2,'N',90),(2,1,'Y',100),(3,1,'Y',100),(4,1,'Y',50),(4,2,'Y',25),(4,3,'Y',25) 

WITH CTEa 
AS (SELECT ID, 
      Prog, 
      T, 
      Qt, 
      Cnt = COUNT(ID) OVER (PARTITION BY ID) 
    FROM dbo.a 
    ), 
    CTEb 
AS (SELECT ID, 
      Prog, 
      T, 
      Qt, 
      Cnt = COUNT(ID) OVER (PARTITION BY ID) 
    FROM dbo.b 
    ) 
SELECT ID_A = a.ID, 
     ID_B = b.ID, 
     b.Prog, 
     b.T, 
     b.Qt, 
     b.Cnt 
FROM CTEa AS a 
    INNER JOIN CTEb AS b 
    ON a.Prog = b.Prog 
     AND a.T = b.T 
     AND a.Qt = b.Qt 
     AND a.Cnt = b.Cnt; 

Ergebnisse:

ID_A ID_B Prog T Qt Cnt 
b  1  1  Y 10 2 
b  1  2  N 90 2 
+0

Das ist nützlich, ich vermutete, es könnte eine Menge Arbeit sein, sich auf 2 Dutzende von Werten einzulassen, aber für den Fall, dass es nichts Besseres gibt, werde ich entweder mit dieser oder mit der Gordon-Linoff-Lösung gehen. Vielen Dank! – MaZe

+1

@MaZe Ich dachte, dass 'c' und' 4' nicht übereinstimmen sollten. – SqlZim

+0

@SqlZim Sie sind völlig richtig. Ich hatte die Ergebnistabelle nicht vollständig überprüft, nur "b" und "1" sind gleich. In der Tat, jetzt, wo ich sehe, was Gordon Lösung besser macht, ist genau die Tatsache, dass er für die gleiche Anzahl von Zeilen überprüft. Danke, dass ich es sehen durfte! – MaZe

Verwandte Themen