2017-07-07 2 views
1

Da diese Tabellen zur Verfügung gestellt:Suche alle Zeilen mit den gleichen genauen Beziehungen wie in einer anderen Tabelle


Tabelle: Test

Spalten:

  • TestID int PK
  • Name nvarchar (128) EINZIGARTIG NICHT NULL

Tabelle: [Test-Eingänge]

Spalten

  • inputsTableName nvarchar (128) UNIQUE PK
  • TestID int PK FK

temporäre Tabelle: ## TestSearchParams

Spalten:

  • inputsTableName nvarchar (128) UNIQUE NOT NULL

Ich brauche Tests zu finden, die Einträge in Test-Eingänge mit inputsTableNames haben passende GENAU alle Einträge in ## TestSearchParams ; Die resultierenden Testbeziehungen müssen genau denen in ## TestSearchParams entsprechen.

Im Wesentlichen finde ich Tests mit NUR den gegebenen Beziehungen, nicht mehr und nicht weniger. Ich passe Namen mit LIKE und Wildcards, aber das ist eine Randbemerkung, die ich glaube, dass ich lösen kann, nachdem die Kernlogik für genaues Matching da ist.

Dies ist meine aktuelle Abfrage:

Select * 
From Tests As B 
Where B.testID In (
         Select ti 
         From (
            Select (
               Select Count(inputsTableName) 
               From [Test-Inputs] 
               Where [Test-Inputs].testID = B.testID 
              ) - Count(Distinct i1) As delta, 
              ti 
            From  (
               Select [Test-Inputs].inputsTableName As i1, 
                 [Test-Inputs].testID As ti 
               From ##TableSearchParams 
               Join [Test-Inputs] 
                On [Test-Inputs].inputsTableName Like ##TableSearchParams.inputsTableName 
                 And B.testID = [Test-Inputs].testID 
              ) As A 
            Group By ti 
          ) As D 
         Where D.delta = 0 
        ); 

Das aktuelle Problem ist, dass seine Tests mit einem Spiel auf alle Einträge in ## TableSearchParams abgerufen werden scheint. Ich habe schon vorher verschiedene andere Abfragen ausprobiert, die unterschiedlich erfolgreich waren. Ich habe funktionierende Abfragen, um Tests zu finden, die mit irgendeinem der Parameter, allen Parametern und keinem der Parameter übereinstimmen - ich kann diese Abfrage einfach nicht funktionieren lassen.

Hier sind einige Beispiele für Tabellenwerte:

Tests

  • 1, Test1
  • 2, Test2
  • 3, Test3

[Test-Eingänge]

  • Tabelle 1, 1
  • Table2, 2
  • Tabelle 1, 3
  • Tabelle 2, 3

TestSearchParams

  • Tabelle1
  • Table2

Die angegebenen Werte sind nur zurückkehren (3, Test3)

+2

Bearbeiten Sie Ihre Frage und bieten Beispieldaten und gewünschte Ergebnisse. –

+0

in Ordnung Beispiele sollten geschrieben werden – DeceitfulEcho

+0

Hier ist ein großartiger Ort, um zu beginnen. http://spaghettiba.com/2015/04/24/how-to-post-at-sql-question-on-a-public-forum/ –

Antwort

-1

Hier ist eine mögliche Lösung, indem man den kompletten Satz von TestInputs für jeden Datensatz in Tests, links Beitritt zu dem Satz von Suchparametern arbeitet, und dann Aggregieren die Ergebnisse durch Test und zwei Beobachtungen:

Erstens, wenn ein Datensatz aus Tests einen TestInput enthält, der nicht zu den Suchparametern gehört, dann muss dieser Datensatz aus der Ergebnismenge ausgeschlossen werden. Wir können dies überprüfen, indem wir sehen, ob es Fälle gibt, in denen der oben beschriebene Link-Join keine Übereinstimmung in der Suchparametertabelle erzeugt hat.

Zweitens, wenn ein Datensatz aus Tests die erste Bedingung erfüllt, dann wissen wir, dass es keine überflüssigen TestInput-Datensätze gibt. Das einzige Problem könnte sein, dass ein Suchparameter existiert, der nicht zu den TestInputs gehört . Wenn dies der Fall ist, ist die Anzahl der Datensätze, die wir für diesen Test gesammelt haben, geringer als die Gesamtzahl der Suchparameter.

Ich habe hier die Annahme gemacht, dass Sie keine Testsätze mit doppelten TestInputs haben und dass Sie ebenfalls keine doppelten Suchparameter verwenden. Wenn diese Annahmen nicht gültig sind, wird dies komplizierter. Aber wenn sie sind, dann sollte dies funktionieren:

declare @Tests table (testID int, [name] nvarchar(128)); 
declare @TestInputs table (testID int, inputsTableName nvarchar(128)); 
declare @TestSearchParams table (inputsTableName nvarchar(128)); 

-- Sample data. 
-- 
-- testID 1 has only a subset of the search parameters. 
-- testID 2 matches the search parameters exactly. 
-- testID 3 has a superset of the search parameters. 
-- 
-- Therefore the result set should include testID 2 only. 
insert @Tests values 
    (1, 'Table A'), 
    (2, 'Table B'), 
    (3, 'Table C'); 
insert @TestInputs values 
    (1, 'X'), 
    (2, 'X'), 
    (2, 'Y'), 
    (3, 'X'), 
    (3, 'Y'), 
    (3, 'Z'); 
insert @TestSearchParams values 
    ('X'), 
    ('Y'); 

declare @ParamCount int; 
select @ParamCount = count(1) from @TestSearchParams; 

select 
    Tests.testID, 
    Tests.[name] 
from 
    @Tests Tests 
    inner join @TestInputs Inputs on Tests.testID = Inputs.testID 
    left join @TestSearchParams Search on Inputs.inputsTableName = Search.inputsTableName 
group by 
    Tests.testID, 
    Tests.[name] 
having 
    -- If a group includes any record where Search.inputsTableName is null, it means that 
    -- the record in Tests has a TestInput that is not among the search parameters. 
    sum(case when Search.inputsTableName is null then 1 else 0 end) = 0 and 

    -- If a group includes fewer records than there are search parameters, it means that 
    -- there exists some parameter that was not found among the Tests record's TestInputs. 
    count(1) = @ParamCount; 
+0

Dies funktioniert perfekt (mit ein bisschen Basteln, um es zu passen voller Umfang meiner Datenbank und Projekt). Danke vielmals! Ich wusste nicht, dass Sie Dinge wie Case-Anweisungen in Where-Klauseln verwenden können - macht das Leben viel einfacher. – DeceitfulEcho

Verwandte Themen