Избегайте множественных выражений `или`


13

У меня есть следующий SQL оракула и его работы и все, но это довольно уродливо со всеми orс. Есть ли более краткий способ сделать это?

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

Ответы:


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 был такой синтаксис.
Росс Прессер

@RossPresser Я думаю, что есть пункт / предложение Connect для добавления синтаксиса. Вы можете голосовать;)
ypercubeᵀᴹ

Я обнаружил , что там есть что - то грубо , как способный: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
Росс Прижимная

но я хотел бы этот фактический синтаксис. Любая идея, где находится элемент подключения?
Росс Прессер

@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 Здесь

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.