Vermeiden Sie Mehrfachausdrücke

13

Ich habe das folgende Orakel SQL und seine Arbeiten und alle, aber es ist mit allen ors ziemlich hässlich . Gibt es eine präzisere Möglichkeit, dies zu tun?

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
quelle

Antworten:

21

Möglicherweise bevorzugen Sie Folgendes:

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

DBFiddle hier

Jack sagt, versuchen Sie es mit topanswers.xyz
quelle
2
Ich wünschte, MS SQL Server hätte diese Syntax.
Ross Presser
@ RossPresser Ich denke, es gibt ein Connect-Element / einen Vorschlag für die hinzuzufügende Syntax. Du kannst abstimmen;)
ypercubeᵀᴹ
Ich fand , dass es ist etwas grob als fähig: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
aber ich möchte diese aktuelle syntax. Haben Sie eine Idee, wo sich das Connect-Objekt befindet?
Ross Presser
@ RossPresser hier ist es: Unterstützung für ANSI-Standardzeilenwertkonstruktoren hinzufügen Die Antwort von MS lautete: "Hallo. Vielen Dank für Ihr Feedback. Wir erwägen sicherlich Zeilenwertkonstruktoren für eine zukünftige Version von SQL Server." Zumindest ist die Anfrage noch offen, 10 Jahre jetzt.
ypercubeᵀᴹ
11

In Bezug auf eine reine Codebereinigung sieht Folgendes sauberer aus:

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

Abhängig von der Anwendung und wie oft die Logik wiederverwendet wird, kann es auch sinnvoll sein, eine Nachschlagetabelle einzurichten, um die Logik anzuwenden:

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

Hier ist eine andere Möglichkeit, dies zu tun. Die Verwendung von where (col1, col2) kann dazu führen, dass Oracle keine Indizes verwendet. Dies sieht für die Abfrage jedoch wie eine Tabelle aus, sodass es möglicherweise besser funktioniert. Sie werden es wissen, sobald Sie die verschiedenen Versionen getestet haben.

  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 hier

Gandolf989
quelle