2009-09-25 9 views
12

Biorąc pod uwagę bazę danych tak:użyciu krotki w SQL w klauzuli

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; 

chciałbym zrobić coś na wzór

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

aby uzyskać odpowiedź „jeden”, „trzy” , ale pojawia się "blisko", ": błąd składni"

Czy to możliwe w każdym smaku SQL? (Używam sqlite)

Czy popełniam błąd koncepcyjny brutto? Albo co?

Odpowiedz

18

Twój kod działa, jeśli robisz to w PostgreSQL lub Oracle. na MS SQL, nie jest obsługiwana

użyj:

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 stwierdzając intencji:

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

to trochę kulawy, na więcej niż dekadę, MS SQL wciąż nie ma pierwszej klasy obsługi krotek. W konstrukcji krotki jest bardziej czytelny niż jego analogiczny konstrukt EXISTS. btw, JOIN działa również (kod Totera), ale jeśli potrzebujesz czegoś bardziej elastycznego i przyszłościowego, użyj EXISTS.

[EDIT]

mówiąc o SQLite, Jestem dabbling z nim niedawno. Tak, IN krotek nie działa

+0

ostateczna odpowiedź za 10 minut! nie działa w sqlite :-( odrzucone i zaakceptowane –

+0

Nawet jeśli działało w języku sqlite, nie polecałbym tego robić, ponieważ zmyli to przyszłych opiekunów Twojego kodu. (UWAGA: jesteś przyszłością opiekun, więc to ty będziesz zdezorientowany) – tster

+4

@tster - Nie widzę źródła jakiegokolwiek zamieszania –

2

można użyć dołączyć:

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

To działa. Plus odpowiedź pojawiła się za 5 minut! Ciągle interesuje mnie, czy mój proponowany kod jest możliwy/beznadziejnie źle rozumiany/cokolwiek? –

+0

Tak, próbujesz pisać w sposób, który rozumiesz, ale problem ten rozwiązuje się znacznie bardziej naturalnie, używając teorii zbiorów, podstawy SQL. Bardzo częstym zastosowaniem SQL jest dołączenie dwóch tabel, aby uzyskać ich przecięcie, co właśnie próbujesz zrobić. – RedFilter

+0

@ OrbMan: IN jest bardziej intuicyjny; DOŁĄCZ DO CZASU, jest zbyt zajęty informatyką. I jest to tylko kwestia posiadania więcej pierwszorzędnej konstrukcji z języka, aby móc osiągnąć coś łatwiejszego (pomyślmy o właściwościach C# w stosunku do ustawiacza Java/gettera). Jeśli IN działa dla pojedynczej wartości, myślę, że będziesz bardziej niż zadowolony, jeśli RDBMS, którego używasz, działa również na sparowanych wartościach (krotkach) –

1

Inną alternatywą jest użycie konkatenacji, aby Państwa 2-krotki w jednej dziedzinie:

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

... po prostu mieć świadomość, że złe rzeczy mogą się zdarzyć, jeśli lub b zawiera separator "-"

+1

To rozwiązanie miałoby inną wadę: optymalizator zapytań nie może uzasadnić takich wyrażeń, a zatem nie może zoptymalizować zapytania. – iuzuz

Powiązane problemy