Evitar múltiples expresiones `o`


13

Tengo el siguiente Oracle SQL y sus trabajos y todo, pero es bastante feo con todos los ors. ¿Hay una manera más concisa de hacer esto?

SELECT * FROM foobar WHERE
  (SUBJECT ='STAT' and TERM ='111') or  
  (SUBJECT ='STAT' and TERM ='222') or  
  (SUBJECT ='ENGLISH' and TERM ='555') or 
  (SUBJECT ='COMM' and TERM ='444') or
  (SUBJECT ='COMM' and TERM ='333') or  
  (SUBJECT ='STAT' and TERM ='666')
  ...

Respuestas:


21

Es posible que prefiera algo como esto:

select *
from foobar
where (subject,term) in ( ('STAT','111')
                         ,('STAT','222')
                         ,('ENGLISH','555')
                         ,('COMM','444')
                         ,('COMM','333')
                         ,('STAT','222')
                         ,('STAT','666') 
                        );

DBFiddle aquí


2
Desearía que MS SQL Server tuviera esta sintaxis.
Ross Presser

@RossPresser Creo que hay un elemento / sugerencia de Connect para agregar la sintaxis. Puedes votar;)
ypercubeᵀᴹ

He descubierto que hay es algo más o menos como capaz:SELECT * FROM foobar INNER JOIN (SELECT * FROM (VALUES ('4','a'),('5','b')) AS myTable(subject,term)) ON myTable.subject=foobar.table and mytable.term=foobar.term
Ross Presser

pero me gustaría esta sintaxis real ¿Alguna idea de dónde está el elemento Connect?
Ross Presser

@RossPresser aquí está: Agregue soporte para constructores de valores de fila estándar ANSI La respuesta de MS fue: "Hola. Gracias por sus comentarios. Ciertamente estamos considerando constructores de valores de fila para una futura versión de SQL Server". Al menos la solicitud aún está abierta, hace 10 años.
ypercubeᵀᴹ

11

En términos de una limpieza de código puro, lo siguiente se ve más limpio:

SELECT * 
  FROM foobar 
  WHERE (SUBJECT = 'STAT' and TERM IN ('111','222','666') )
    OR  (SUBJECT = 'COMM' and TERM IN ('333','444') )
    OR  (SUBJECT = 'ENGLISH' and TERM = '555' ) ;

Dependiendo de la aplicación y con qué frecuencia se reutilizará la lógica, también puede valer la pena configurar una tabla de búsqueda para aplicar la lógica:

CREATE TABLE foobar_lookup (SUBJECT VARCHAR2(7), TERM VARCHAR2(3)) ;

INSERT INTO foobar_lookup SELECT 'STAT',    '111' FROM dual ;
INSERT INTO foobar_lookup SELECT 'STAT',    '222' FROM dual ;
INSERT INTO foobar_lookup SELECT 'STAT',    '666' FROM dual ;
INSERT INTO foobar_lookup SELECT 'COMM',    '444' FROM dual ;
INSERT INTO foobar_lookup SELECT 'COMM',    '333' FROM dual ;
INSERT INTO foobar_lookup SELECT 'ENGLISH', '555' FROM dual ;

SELECT f.* FROM foobar f
JOIN foobar_lookup fl 
    ON fl.subject = f.subject
    AND fl.term = f.term ;

4

Aquí hay otra forma de hacerlo. El uso de where (col1, col2) puede hacer que Oracle no use ningún índice, pero esto parece una tabla para la consulta, por lo que podría funcionar mejor. Lo sabrá una vez que pruebe las diferentes versiones.

  WITH subject_terms 
            (subject,   term) AS
    ( SELECT 'STAT'   , '111' FROM dual UNION ALL
      SELECT 'STAT'   , '222' FROM dual UNION ALL
      SELECT 'ENGLISH', '555' FROM dual UNION ALL
      SELECT 'COMM'   , '444' FROM dual UNION ALL
      SELECT 'COMM'   , '333' FROM dual UNION ALL
      SELECT 'STAT'   , '666' FROM dual )
SELECT * 
  FROM foobar             fb
 INNER JOIN subject_terms st
    ON fb.subject = st.subject
   AND fb.term    = st.term;

DBFiddle Here

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.