2012-11-17 6 views
11

Diciamo che ho una tabella, email_phone_notes che assomiglia a questo:MySQL: come massa selezionare le righe con più coppie nella clausola WHERE

+-----------------------+--------------+------+-----+---------+-------+ 
| Field     | Type   | Null | Key | Default | Extra | 
+-----------------------+--------------+------+-----+---------+-------+ 
| email     | varchar  | NO | PRI | NULL |  | 
| phone     | varchar  | NO | PRI | NULL |  | 
| notes     | text   | NO |  | 0  |  | 
+-----------------------+--------------+------+-----+---------+-------+ 

Così, ogni combinazione e-mail/telefono è unico, ma si potrebbe avere diversi indirizzi e-mail con numeri di telefono diversi e viceversa. Questo è un po 'forzato ma rispecchia il mio scenario.

Mi piacerebbe fare una query come questa:

SELECT * FROM email_phone_notes  WHERE email = '[email protected]' AND phone = '555-1212'; 

Ma, mi piacerebbe fare più coppie in una sola volta in modo da non devo fare diverse SELECT query. È anche importante tenere insieme le coppie perché non voglio restituire una combinazione errata di telefono/email che non è stata richiesta.

Potrei fare qualcosa del genere, ma per la possibilità di diverse centinaia di valori la query sarà davvero lunga.

SELECT * FROM email_phone_notes WHERE ( 
    (email='[email protected]' && phone='555-1212') || 
    (email='[email protected]' && phone='888-1212') || 
    ... 

C'è una soluzione più elegante, o dovrei restare con questo? Grazie!

risposta

21

Se siete alla ricerca elegante SQL, è possibile utilizzare i costruttori di fila:

SELECT * FROM email_phone_notes WHERE (email, phone) IN (
    ('[email protected]' , '555-1212'), 
    ('[email protected]', '888-1212') 
    -- etc. 
); 

Tuttavia, questo non è affatto indice-friendly e non sarebbe raccomandato su un tavolo di qualsiasi dimensione significativa. Invece, si potrebbe materializzare un tavolo con le coppie di volute e unisciti che con il vostro tavolo:

SELECT * FROM email_phone_notes NATURAL JOIN (
    SELECT '[email protected]' AS email, '555-1212' AS phone 
UNION ALL 
    SELECT '[email protected]', '888-1212' 
-- etc. 
) t; 

Oppure precompilare una (temporanea) della tabella:

CREATE TEMPORARY TABLE foo (PRIMARY KEY (email, phone)) Engine=MEMORY 
    SELECT email, phone FROM email_phone_notes WHERE FALSE 
; 

INSERT INTO foo 
    (email, phone) 
VALUES 
    ('[email protected]' , '555-1212'), 
    ('[email protected]', '888-1212') 
    -- etc. 
; 

SELECT * FROM email_phone_notes NATURAL JOIN foo; 
+2

wow che è grande SYNTAX! –

1

è possibile utilizzare un row constructor come questo :

SELECT * 
FROM email_phone_notes 
WHERE (email, phone) IN (
    ('[email protected]', '555-1212'), 
    ('[email protected]', '888-1212') 
) 

SQLfiddle example

+1

Purtroppo non useremo l'indice, comunque. – eggyal

+1

Maledizione, MySQL. Bene, l'originale non sembra nemmeno: http://sqlfiddle.com/#!2/86c1e/2 – AndreKR

+0

Ricorda che un indice non verrebbe comunque utilizzato su quel tavolo, poiché è troppo piccolo (meno di 10 record). – eggyal