Unikanie wielu wyrażeń `lub`

13

Mam następujący Oracle SQL i jego działa i wszystko, ale jest dość brzydkie ze wszystkimi ors. Czy istnieje bardziej zwięzły sposób na zrobienie tego?

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
źródło

Odpowiedzi:

21

Może wolisz coś takiego:

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

DBFiddle tutaj

Jack mówi, że spróbuj topanswers.xyz
źródło
2
Chciałbym, żeby MS SQL Server miał tę składnię.
Ross Presser
@RossPresser Myślę, że istnieje element / sugestia Connect do dodania składni. Możesz głosować;)
ypercubeᵀᴹ
Przekonałem się, że jest coś w przybliżeniu równie zdolnego: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
ale chciałbym tę rzeczywistą składnię. Masz pomysł, gdzie jest element Connect?
Ross Presser
@RossPresser tutaj: Dodaj obsługę standardowych konstruktorów wartości wierszy ANSI Odpowiedź od MS była następująca: „Cześć. Dziękujemy za opinię. Z pewnością rozważamy konstruktory wartości wierszy dla przyszłej wersji SQL Server”. Przynajmniej prośba jest nadal otwarta, za 10 lat.
ypercubeᵀᴹ
11

Jeśli chodzi o czyste czyszczenie kodu, następujące elementy wyglądają na czystsze:

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

W zależności od aplikacji i tego, jak często logika będzie ponownie wykorzystywana, warto również ustawić tabelę odnośników, aby zastosować logikę:

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
źródło
4

Oto inny sposób, aby to zrobić. Użycie where (col1, col2) może spowodować, że Oracle nie użyje żadnych indeksów, ale wygląda to jak tabela zapytania, więc może działać lepiej. Dowiesz się, gdy przetestujesz różne wersje.

  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

Gandolf989
źródło