Menghindari banyak ekspresi `atau`

13

Saya memiliki oracle SQL berikut dan karya-karyanya dan semua tapi itu cukup jelek dengan semua ors. Apakah ada cara yang lebih ringkas untuk melakukan ini?

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
sumber

Jawaban:

21

Anda mungkin lebih suka sesuatu seperti ini:

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

DBFiddle di sini

Jack berkata coba topanswers.xyz
sumber
2
Saya berharap MS SQL Server memiliki sintaks ini.
Ross Presser
@RossPresser Saya pikir ada item Hubungkan / saran untuk sintaks yang akan ditambahkan. Anda dapat memilih;)
ypercubeᵀᴹ
Saya menemukan bahwa ada adalah sesuatu yang kira-kira sebagai mampu: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
tapi saya ingin sintaks yang sebenarnya ini. Adakah yang tahu di mana item Connect berada?
Ross Presser
@RossPresser di sini adalah: Tambahkan dukungan untuk konstruktor nilai baris standar ANSI . Jawaban dari MS adalah: "Halo. Terima kasih atas umpan balik Anda. Kami tentu mempertimbangkan konstruktor nilai baris untuk rilis SQL Server di masa mendatang." Setidaknya permintaan masih terbuka, 10 tahun sekarang.
ypercubeᵀᴹ
11

Dalam hal pembersihan kode murni, berikut ini terlihat lebih bersih:

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

Bergantung pada aplikasi dan seberapa sering logika akan digunakan kembali, mungkin perlu juga menyiapkan tabel pencarian untuk menerapkan logika:

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
sumber
4

Ini cara lain untuk melakukannya. Menggunakan where (col1, col2) dapat menyebabkan Oracle tidak menggunakan indeks apa pun, tetapi ini terlihat seperti tabel untuk kueri, sehingga mungkin berfungsi lebih baik. Anda akan tahu setelah Anda menguji berbagai versi.

  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 Di Sini

Gandolf989
sumber