2011-11-04 17 views
30

Tengo una tabla que contiene los campos group_id y group_type y quiero consultar la tabla para todos los registros que tienen cualquier tupla (Identificación del grupo, grupo de tipo) de una lista de tuplas. Por ejemplo, quiero ser capaz de hacer algo como:El uso de tuplas en SQL "IN" cláusula

SELECT * 
FROM mytable 
WHERE (group_id, group_type) IN (("1234-567", 2), ("4321-765", 3), ("1111-222", 5)) 

Una pregunta muy similar ya se pidió en: using tuples in sql in clause, pero la solución propuesta no presupone la lista de tuplas es que ser recuperado de otra tabla. Esto no funciona en mi caso, los valores de la tupla están codificados.

Una solución es utilizar concatenación de cadenas:

SELECT * 
FROM mytable 
WHERE group_id + STR(group_type, 1) IN ("1234-5672", "4321-7653", "1111-2225") 

Pero el problema es que la mesa es bastante grande y hacer una concatenación de cadenas y la conversión para cada registro sería muy caro.

¿Alguna sugerencia?

Respuesta

8

Por qué no construir las declaraciones O?

SELECT * 
FROM mytable 
WHERE (group_id = '1234-567' and group_type = 2) 
    OR (group_id = '4321-765' and group_type = 3) 
    OR (group_id = '1111-222' and group_type = 5) 

Por supuesto, no se ve tan bonito y limpio como tu ejemplo concepto, pero que va a hacer el trabajo (y si existieras que IN con tuplas, sería aplicar exactamente de la misma manera bajo las portadas más . probable

+1

¡Buen punto! El único problema es en caso de que tengas una larga lista de tuplas. – Rafid

2

Utilizando esta solución, esto debería funcionar:

SELECT * 
FROM mytable m 
WHERE EXISTS (
    SELECT * FROM (
    SELECT "1234-567" group_id, 2 group_type UNION ALL 
    SELECT "4321-765", 3 UNION ALL 
    SELECT "1111-222", 5) [t] 
    WHERE m.group_id = t.group_id AND m.group_type = t.group_type) 

Por cierto, probablemente debería utilizar un CTE para crear esa tabla interna.

6

Se puede utilizar una expresión de tabla común pretender que estas tuplas están en otra tabla:

;WITH Tuples as (
    select '1234-567' as group_id, 2 as group_type union all 
    select '4321-765', 3 union all 
    select '1111-222', 5 
) 
SELECT * /* TODO - Pick appropriate columns */ 
from mytable m where exists (
    select * from Tuples t 
    where m.group_id = t.group_id and m.group_type = t.group_type) 
+2

Gracias, pero ¿por qué hay un punto y coma antes de la cláusula? – Rafid

+3

@Promather: está ahí porque la palabra clave 'WITH' puede tener otros significados, y para introducir un CTE, debe ser el comienzo de una declaración. El punto y coma garantiza que la declaración anterior termine definitivamente. –

21

En SQL Server 2008 se puede hacer así:

select * 
from mytable as T 
where exists (select * 
       from (values ('1234-567', 2), 
          ('4321-765', 3), 
          ('1111-222', 5)) as V(group_id, group_type) 
       where T.group_id = V.group_id and 
        T.group_type = V.group_type    
      ) 
+1

¿Qué es específico de SQL Server 2008? ¿Es la parte "de los valores"? – Rafid

+0

@Promather, sí, son los valores. La alternativa es usar 'select ... union all' como en la respuesta de B Tyler. –

+0

¡Genial! ¿Es esto posible en SQL Server 2008? Esto muestra lo que es el significado de la expresión de valor de fila claramente. – kangbu

31

dado un pellizco muy menor (reemplazar comillas dobles con sencillo y añadir la palabra clave VALUES), la sintaxis propuesta es válida estándar SQL-92 sintaxis, es decir,

SELECT * 
    FROM mytable 
WHERE (group_id, group_type) IN (
            VALUES ('1234-567', 2), 
             ('4321-765', 3), 
             ('1111-222', 5) 
           ); 

Lamentablemente, no MSFT han agregado a SQL Server y consider it an 'unplanned' feature.

+0

La retroalimentación de esta característica parece haberse trasladado a UserVoice: https://feedback.azure.com/forums/908035-sql-server/suggestions/32894992-add-support-for-ansi-standard-row-value-constructo –

0

Aquí está otra solución tupla usando una combinación:

SELECT 
    * 
FROM mytable m 
JOIN 
(
    SELECT "1234-567" group_id, 2 group_type 
    UNION ALL SELECT "4321-765", 3 
    UNION ALL SELECT "1111-222", 5 
) [t] 
ON m.group_id = t.group_id 
AND m.group_type = t.group_type 
Cuestiones relacionadas