2016-07-06 97 views
18

Mi sono imbattuto nella query (valida) successiva in MySQL (funziona anche in Oracle/MSSQL quando si sostituisce = con IN):Qual è la differenza quando si confronta con parentesi: WHERE (a, b) = (1,2)

SELECT * from mytable WHERE (a, b)=(1,2) 

E 'lo stesso di

SELECT * from mytable WHERE a=1 and b=2 

credo che la definizione del MySQL docs è qui:

simple_expr: 
    [...] 
    | (expr [, expr] ...) 
    [...] 

Come si chiama? Ci sono pro e contro per usarlo?

+0

Pro. Meno battitura. Cons. Non posso usare gli indici credo - ma non sono sicuro- facile da verificare anche se – Strawberry

+0

in un primo test 'EXPLAIN' mi dice che gli stessi indici sono usati in entrambe le query, sembra che non ci siano differenze qui –

+0

Penso che la prima sintassi è meno chiara se la clausola where è più complessa –

risposta

14

Può essere molto utile quando aveva bisogno di confrontare più colonne a più combinazione di valori utilizzando IN():

SELECT * FROM YourTable 
WHERE (col1,col2) IN((1,2),(2,3),(4,4)...) 

Invece di:

SELECT * FROM YourTable 
WHERE (col1 = 1 and col2 = 2) OR 
     (col1 = 2 and col2 = 3) OR 
     (col1 = 4 and col2 = 4) OR 
     .... 

Dopo aver esaminato il piano di esecuzione di entrambe le query, Posso dire che in Oracle (usando IN() che è fondamentalmente lo stesso), l'ottimizzatore valuta allo stesso modo e entrambi stanno usando gli indici:

condizioni separati:

EXPLAIN PLAN FOR 
SELECT * FROM dim_remedy_tickets_cache t 
where t.tt_id = '1' and t.region_name = 'one'; 

6 | 0 | SELECT STATEMENT   |        |  1 | 311 | 30 (0)| 00:00:01 | 
7 | 1 | TABLE ACCESS BY INDEX ROWID| DIM_REMEDY_TICKETS_CACHE  |  1 | 311 | 30 (0)| 00:00:01 | 
8 | 2 | INDEX RANGE SCAN   | DIM_REMEDY_TICKETS_HISTORYPK |  1 |  | 20 (0)| 00:00:01 | 

condizioni combinate:

EXPLAIN PLAN FOR 
SELECT * FROM dim_remedy_tickets_cache t 
where (t.tt_id,t.region_name) in (('1','one')) 

6 | 0 | SELECT STATEMENT   |        |  1 | 311 | 30 (0)| 00:00:01 | 
7 | 1 | TABLE ACCESS BY INDEX ROWID| DIM_REMEDY_TICKETS_CACHE  |  1 | 311 | 30 (0)| 00:00:01 | 
8 | 2 | INDEX RANGE SCAN   | DIM_REMEDY_TICKETS_HISTORYPK |  1 |  | 20 (0)| 00:00:01 | 

Mi assumo ogni RDBMS valuteranno questo interroga lo stesso.

I costruttori di riga sono legali in altri contesti. Ad esempio, le seguenti due affermazioni sono semanticamente equivalenti (e vengono gestiti nello stesso modo dal ottimizzatore):

Quindi:

Contro - può essere meno leggibile per alcune persone, ma in fondo non contro.

Pros - meno codice, e la combinazione di confronto più colonne utilizzando IN():

+0

Quindi questo funziona anche in Oracle (non funziona in SQL Server). –

+3

Molto utile quando si esegue 'IN', ad es. 'WHERE (a, b) IN (SELEZIONA c1, c2 FROM ...'. – jarlh

+0

@jarlh Hai ragione, aggiornato – sagi

0

Io non credo che ci sia alcuna differenza tra queste due query, l'ottimizzatore probabilmente fare lo stesso.

È necessario eseguire un piano di esecuzione su entrambe le query e vedere per conto proprio.

Oltre a questo, è più di una preferenza. Non ci sono molti Contro e Pro qui per entrambe le parti, quindi scegli quello che ti piace di più.