Éviter plusieurs expressions `ou`

13

J'ai l'oracle SQL suivant et ses travaux et tout, mais c'est assez moche avec tous les ors. Existe-t-il une manière plus concise de procéder?

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')
  ...
Kyle Decot
la source

Réponses:

21

Vous pourriez préférer quelque chose comme ça:

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

DBFiddle ici

Jack dit d'essayer topanswers.xyz
la source
2
Je souhaite que MS SQL Server ait cette syntaxe.
Ross Presser
@RossPresser Je pense qu'il y a un élément / suggestion Connect pour la syntaxe à ajouter. Vous pouvez voter;)
ypercubeᵀᴹ
Je trouve qu'il y a quelque chose à peu près aussi capable: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
mais je voudrais cette syntaxe réelle. Vous savez où se trouve l'élément Connect?
Ross Presser
@RossPresser le voici: ajouter la prise en charge des constructeurs de valeurs de lignes standard ANSI La réponse de MS était: "Bonjour. Merci pour vos commentaires. Nous envisageons certainement les constructeurs de valeurs de lignes pour une future version de SQL Server." Au moins la demande est toujours ouverte, 10 ans maintenant.
ypercubeᵀᴹ
11

En termes de nettoyage de code pur, ce qui suit semble plus propre:

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' ) ;

Selon l'application et la fréquence de réutilisation de la logique, il peut également être utile de configurer une table de recherche pour appliquer la logique:

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 ;
Thomas Cleberg
la source
4

Voici une autre façon de procéder. L'utilisation de où (col1, col2) peut empêcher Oracle d'utiliser des index, mais cela ressemble à une table pour la requête, donc cela pourrait mieux fonctionner. Vous saurez une fois que vous aurez testé les différentes versions.

  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 ici

Gandolf989
la source