Operatoren ähnlich 'in', die zwei Sätze vergleichen

7

Ich möchte zwei Wertesätze vergleichen und sehen, ob es Schnittpunkte gibt. Der erste Wertesatz wird zur Laufzeit angegeben und der zweite Wertesatz wird in einer Zeile einer Datenbank gespeichert.

Hier sind einige Beispielcodes:

CREATE TABLE #tab1 (var1 INT, var2 INT , var3 INT)

INSERT INTO #tab1 
VALUES (1,2,3),(0,0,0),(0,4,0)

Select
a = (case when 1 IN (var1,var2,var3) OR
               2 IN (var1,var2,var3) OR
               3 IN (var1,var2,var3)
    THEN 1 else 0 end) 
from #tab1

Ich halte den Code für zu umständlich und frage mich, ob es einen einfachen Weg gibt, dies zu tun. Vielen Dank!

Jason
quelle
1
Möchten Sie zwei Wertesätze (dh zwei Zeilensätze in einer Tabelle) oder zwei Variablensätze (eine begrenzte Anzahl von ihnen) vergleichen und feststellen, welche Werte gleich sind? Ihr Code impliziert 3 Variablen und der zweite Satz ist 1,2,3, richtig? Können Sie Beispiele für die beiden Sätze geben? Bitte geben Sie ein positives und ein negatives Beispiel.
Grimaldi
@Grimaldi, danke für deine Erinnerung und ich habe die Frage aktualisiert. Bitte schauen Sie nach, ob es jetzt klar ist.
Jason
Die Frage ist nun, 3 Spalten mit 3 Laufzeitwerten zu vergleichen und eine übereinstimmende Spalte zu melden. Dies würde "vereinfacht", indem die Tabelle in eine Spalte mit den Werten konvertiert wird, was Sie mit "SELECT-Taste, var1 FROM # tab1 UNION ALL SELECT-Taste, var2 ... UNION ALL SELECT-Taste, var3", aber I tun könnten Denken Sie nicht, dass dies besser als Ihr Code ist oder schneller ausgeführt wird. Sie könnten es in eine Ansicht setzen. Ihre Formel gibt 1 in jeder Zeile aus, die 1 oder mehr der Laufzeiteingaben enthält. Ich gehe davon aus, dass Sie diese erhalten möchten, oder möchten Sie im Ergebnis Zeilen mit a = 1 als Ergebnismenge auswählen?
Robert Carnegie
Fragen zu Ihrem überarbeiteten Beispiel: Müssen Sie wirklich alle Zeilen (mit einem Wahrheits- / Falschwert) zurückgeben, oder möchten Sie wirklich nur die Zeilen zurückgeben, in denen eine Ihrer 3 Spalten mit Ihren anderen 3 Werten übereinstimmt? Gibt es andere relevante Spalten, die Sie zurückgeben müssen, z. B. eine ID?
BradC
@BradC, danke für deine Hilfe! Ich brauche alle Zeilen, um zurückgegeben zu werden. Es gibt andere Zeilen, die ich zusammen mit den wahren / falschen Zeilen zurückgeben möchte. Ändert es die Fragen?
Jason

Antworten:

1

Bei drei Setup-Eingaben und einer separaten Wertetabelle funktioniert der folgende Code.

declare @input1 int =1
declare @input2 int =2
declare @input3 int =3

CREATE TABLE #tab1 (var1 INT, var2 INT , var3 INT)
INSERT INTO #tab1 
VALUES (1,2,3),(0,0,0),(0,4,0),(1,4,1),(4,0,0),(0,5,1),(2,4,0),(1,4,3)


 declare @set table(input int)
 insert  @set values (@input1), (@input2),(@input3);

 select distinct #tab1.*, case when join1.i1 is null then 'No Match' else 'match' end matching
 from #tab1
 left join (select distinct a.input i1, b.input i2 ,c.input i3
                from @set a 
                cross join @set b 
                cross join @set c ) join1
    on join1.i1=#tab1.var1
        or join1.i2=#tab1.var2
        or join1.i3=#tab1.var3

Ich denke, das ist es, wonach Sie gesucht haben, wenn Sie 'in' nicht verwenden wollten. Um ehrlich zu sein, würde ich 'in' verwenden. Es ist viel einfacher und einfacher zu schreiben. Der obige Code brauchte einige Zeit, um zu funktionieren. Ich würde Ihren In-Code jedoch wie folgt aktualisieren:

select * ,'match'
from #tab1
where @input1 in (var1, var2, var3)
    or @input2 in (var1, var2, var3)
    or @input3 in (var1, var2, var3)
union 
select * ,'no-match'
from #tab1
where @input1 not in (var1, var2, var3)
    and @input2 not in (var1, var2, var3)
    and @input3 not in (var1, var2, var3)
Anthony Genovese
quelle
Danke für Ihre Hilfe! Als ich diese Frage stellte, dachte ich, dass es eine universelle Funktion geben würde, um solche Fragen zu lösen. Aber es stellte sich anscheinend als keine solche Lösung heraus ...
Jason
10

Sie können nur JOINzu realen oder dynamisch abgeleiteten Tabellen:

DECLARE @var1 INT=2;
DECLARE @var2 INT=15;
DECLARE @var3 INT=-7;

IF EXISTS (SELECT 1 FROM 
             (VALUES (1),(2),(3))tableNums(number)
             INNER JOIN (VALUES (@var1), (@var2), (@var3))tableVars(var)
             ON tableNums.number=tableVars.var
       )
    SELECT 1    --or do something else interesting
ELSE SELECT 0   --or do the opposite

Wenn die Liste sehr lang wäre, würde ich sie wahrscheinlich im Voraus in einer # temp-Tabelle erstellen, anstatt sie in der Anweisung auszuführen, aber die JOINund -Logik EXISTSwäre dieselbe.


Ebenso könnten wir INTERSECTanstelle von JOIN:

CASE WHEN EXISTS ( SELECT * FROM (VALUES (1), (2), (3)) AS x(i) 
                 INTERSECT 
                   SELECT * FROM (VALUES (@var1), (@var2), (@var3)) AS y(i)
                 )
THEN 1 ELSE 0 END 

Test bei dbfiddle.uk .

BradC
quelle
Entschuldigung, meine Frage war überhaupt nicht klar. Die Variablen, auf die ich mich bezog, waren tatsächlich Spalten in der Datenbank. Ihre Antwort kann meine Frage also nicht direkt lösen. Können Sie sich die aktualisierte Frage ansehen? Vielen Dank!
Jason
1
Die Antwort funktioniert gut mit Variablen oder Spalten. Hast Du es versucht?
Ypercubeᵀᴹ
4

Sie können anstelle von CASE Folgendes versuchen

declare @var1 int, @var2 int, @var3 int

set @var1 = 1
set @var2 = 2
Set @var3 = 3

IF 1 IN (@var1, @var2, @var3) or 2 in (@var1, @var2, @var3) or 3 in (@var1, @var2, @var3)
BEGIN
    Select 1;
END

else 
BEGIN
    select 0;
END
Henrico Bekker
quelle
Entschuldigung, meine Frage war überhaupt nicht klar. Die Variablen, auf die ich mich bezog, waren tatsächlich Spalten in der Datenbank. Können Sie sich die aktualisierte Frage ansehen? Vielen Dank!
Jason
1

Wenn Sie die Variablen nicht behalten müssen, können Sie eine Schleife wie z.

SET @found = 0
WHILE @var1 IS NOT NULL AND @found = 0
BEGIN
  IF @var1 IN (1, 2, 3) 
  BEGIN SET @found = 1  END
  ELSE
  BEGIN
    SET @var1 = @var2; SET @var2 = @var3; SET @var3 = NULL
  END
END

... aber das ist nicht tischig. Wir sind Datenbankadministratoren und verwenden Tabellen.

Robert Carnegie
quelle
Vielen Dank für Ihre Hilfe und ich habe die Frage aktualisiert. Können Sie sich das ansehen?
Jason