避免多个`或`表达式


13

我有以下oracle SQL及其工作原理,但与所有ors 比较难看。有更简洁的方法吗?

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

Answers:


21

您可能更喜欢这样的事情:

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

DBFiddle 在这里


2
我希望MS SQL Server具有此语法。
Ross Presser 2015年

@RossPresser我认为要添加语法有一个Connect项目/建议。您可以投票;)
ypercubeᵀᴹ17年

我发现,一些大致为能够: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
罗斯压

但是我想要这个实际的语法。知道Connect项目在哪里吗?
罗斯·普泽德

@RossPresser在这里是:添加对ANSI标准行值构造函数支持 MS的回答是:“您好。谢谢您的反馈。我们肯定会在将来的SQL Server版本中考虑行值构造函数。” 至少10年后,此请求仍未解决。
ypercubeᵀᴹ

11

就纯代码清洗而言,以下代码看起来更干净:

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

根据应用程序和逻辑的重用频率,可能值得设置查找表以应用逻辑:

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

这是另一种方法。使用where(col1,col2)可能会导致Oracle不使用任何索引,但这看起来像查询表,因此可能会更好。一旦测试了各种版本,您就会知道。

  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 在这里

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.