2009-09-25 4 views
12

Bei einer Datenbank wie folgt aus:Tupel in SQL-in-Klausel

BEGIN TRANSACTION; 
CREATE TABLE aTable (
a STRING, 
b STRING); 
INSERT INTO aTable VALUES('one','two'); 
INSERT INTO aTable VALUES('one','three'); 
CREATE TABLE anotherTable (
a STRING, 
b STRING); 
INSERT INTO anotherTable VALUES('one','three'); 
INSERT INTO anotherTable VALUES('two','three'); 
COMMIT; 

Ich möchte etwas tun, nach dem Vorbild der

SELECT a,b FROM aTable 
WHERE (aTable.a,aTable.b) IN 
(SELECT anotherTable.a,anotherTable.b FROM anotherTable); 

Um die Antwort ‚eins‘, ‚drei‘ , aber ich bekomme "nahe", ": syntax error"

Ist dies in jedem Geschmack von SQL möglich? (Ich benutze sqlite)

Mache ich einen groben konzeptionellen Fehler? Oder was?

Antwort

18

Ihr Code funktioniert, wenn Sie es in PostgreSQL oder Oracle tun. auf MS SQL, ist es nicht

unterstützt

Verwendung dieses:

SELECT a,b FROM aTable 
WHERE 
-- (aTable.a,aTable.b) IN -- leave this commented, it makes the intent more clear 
EXISTS 
(
    SELECT anotherTable.a,anotherTable.b -- do not remove this too, perfectly fine for self-documenting code, i.e.. tuple presence testing 
    FROM anotherTable 
    WHERE anotherTable.a = aTable.a AND anotherTable.b = aTable.b 
); 

[EDIT]

sans die Angabe des Vorsatzes:

SELECT a,b FROM aTable 
WHERE  
EXISTS 
(
    SELECT * 
    FROM anotherTable 
    WHERE anotherTable.a = aTable.a AND anotherTable.b = aTable.b 
); 

es ist etwas lahm, für mehr als ein Jahrzehnt, MS SQL immer noch nicht erstklassige Unterstützung für Tupel. Das IN-Tupel-Konstrukt ist deutlich lesbarer als das analoge EXISTS-Konstrukt. Übrigens, JOIN funktioniert auch (Tster-Code), aber wenn Sie etwas flexibler und zukunftssicher benötigen, verwenden Sie EXISTS.

[EDIT]

Rede von SQLite, ich bin vor kurzem mit ihm Dilettantismus. ja, in Tupeln nicht funktioniert

+0

endgültige Antwort in 10 Minuten! funktioniert nicht in sqlite :-( gewählt und akzeptiert –

+0

Selbst wenn es in sqlite funktioniert, würde ich empfehlen, es nicht zu tun.Dies ist verpflichtet, zukünftige Betreuer Ihres Codes zu verwirren. (HINWEIS: Sie sind die Zukunft Maintainer, also bist du es, der verwirrt wird) – tster

+4

@tster - Ich sehe die Quelle der Verwirrung nicht –

2

können Sie mit einem Join:

SELECT aTable.a, aTable.b FROM aTable 
JOIN anotherTable ON aTable.a = anotherTable.a AND aTable.b = anotherTable.b 
+0

Dies funktioniert. Plus die Antwort zeigte sich in 5 Minuten! Noch interessiert zu wissen, ob mein vorgeschlagener Code möglich/hoffnungslos falsch ist/was auch immer? –

+0

Ja, Sie versuchen auf eine Weise zu schreiben, die Sie verstehen, aber dieses Problem wird viel natürlicher gelöst, wenn Sie die Mengenlehre, die Basis von SQL, verwenden. Eine sehr häufige Verwendung von SQL besteht darin, zwei Tabellen zu verbinden, um deren Schnittmenge zu erhalten, was Sie versuchen zu tun. – RedFilter

+0

@OrbMan: IN ist intuitiver; JOIN manchmal, ist zu viel Computer-Science-Looking. Und es ist nur eine Frage von mehr erstklassigem Konstrukt aus einer Sprache, um etwas leichter zu erreichen (denke C# 's Eigenschaften vs Java Setter/Getter). Wenn das IN für einen einzelnen Wert arbeitet, denke ich, dass es dir mehr als gut gefällt, wenn das von dir verwendete RDBMS auch mit gepaarten Werten arbeitet (Tupel) –

1

Eine weitere Alternative ist Verkettung zu verwenden, um Ihre 2-Tupels in ein einzelnes Feld zu machen:

SELECT a,b FROM aTable 
WHERE (aTable.a||'-'||aTable.b) IN 
(SELECT (anotherTable.a || '-' || anotherTable.b FROM anotherTable); 

... nur bewusst sein, dass schlechte Dinge passieren kann, wenn ein oder b enthält das Trennzeichen '-'

+1

Diese Lösung hätte einen weiteren Nachteil: Der Abfrageoptimierer kann solche Ausdrücke nicht nachvollziehen und kann daher die Abfrage nicht optimieren. – iuzuz