2009-09-25 11 views
12

dado una base de datos de la siguiente manera:usando tuplas en SQL en la cláusula

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; 

me gustaría hacer algo en la línea de

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

Para obtener la respuesta 'uno', 'tres' , pero me estoy "acercando", ": error de sintaxis"

¿Es esto posible en cualquier sabor de SQL? (Estoy usando sqlite)

¿Estoy cometiendo un error conceptual grave? ¿O que?

Respuesta

18

su código si lo hace en PostgreSQL u Oracle. en MS SQL, no se admite

uso esto:

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 la enunciación de intenciones:

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

es un poco cojo, durante más de una década, MS SQL todavía no tiene soporte de primera clase para tuplas. La construcción IN tuple es mucho más legible que su construcción EXISTS análoga. Por cierto, JOIN también funciona (código de tster), pero si necesita algo más flexible y a prueba de futuro, use EXISTS.

[EDIT]

hablar de SQLite, estoy incursionando con él recientemente. sí, EN tuplas no funciona

+0

respuesta definitiva en 10 minutos! no funciona en sqlite :-( votado y aceptado –

+0

Incluso si funcionara en sqlite, recomendaría no hacerlo. Esto confundirá a los futuros mantenedores de su código. (NOTA: usted es el futuro mantenedor, entonces eres tú quien se confundirá) – tster

+4

@tster - No veo el origen de ninguna confusión –

2

puede utilizar una combinación: trabaja

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

Esto funciona. ¡Además, la respuesta apareció en 5 minutos! ¿Todavía estoy interesado en saber si mi código propuesto es posible/absolutamente erróneo/lo que sea? –

+0

Sí, estás tratando de escribir de una manera que entiendas, pero este problema se resuelve de manera mucho más natural usando la teoría de conjuntos, la base de SQL. Un uso muy común de SQL es unir dos tablas para obtener la intersección de ellas, que es lo que estás tratando de hacer. – RedFilter

+0

@OrbMan: IN es más intuitivo; ÚNASE a veces, es demasiado científico para la computación. Y es solo cuestión de tener más construcciones de primera clase de un idioma para poder lograr algo más fácil (piense en las propiedades de C# frente a las de Java setter/getter). Si el IN funciona para un solo valor, creo que también estará más que contento si el RDBMS que está utilizando también funciona en valores emparejados (tuplas) –

1

Otra alternativa es utilizar la concatenación para hacer su 2-tupla en un solo campo:

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

... acaba de ser conscientes de que las cosas malas pueden suceder si una o b contiene el delimitador '-'

+1

Esta solución tendría otra desventaja: el optimizador de consultas no puede razonar acerca de tales expresiones y, por lo tanto, no puede optimizar la consulta. – iuzuz

Cuestiones relacionadas