Уникання кількох виразів `або`


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

Відповіді:


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 Я думаю, що є елемент / пропозиція для підключення синтаксису. Ви можете проголосувати;)
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
Росс Пресер,

але я хотів би цього фактичного синтаксису. Будь-яка ідея, де знаходиться елемент 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

Ось ще один спосіб зробити це. Використання місця, де (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.