2009-04-15 8 views
46

ho una query MySQL che unisce due tabelleMySQL join in cui non esiste

  • Votanti
  • Famiglie si uniscono su voters.household_id e household.id

    Ora che cosa devo fare è modificarlo dove il tavolo degli elettori è unito ad un terzo tavolo chiamato eliminazione, lungo voter.id ed elimination.voter_id, come mai il problema è che voglio escludere qualsiasi record nella tabella degli elettori che ha un record corrispondente nell'eliminazione tavolo. come faccio a creare una query per fare questo?

questo è il mio query corrente

SELECT `voter`.`ID`, `voter`.`Last_Name`, `voter`.`First_Name`, 
     `voter`.`Middle_Name`, `voter`.`Age`, `voter`.`Sex`, 
     `voter`.`Party`, `voter`.`Demo`, `voter`.`PV`, 
     `household`.`Address`, `household`.`City`, `household`.`Zip` 
FROM (`voter`) 
JOIN `household` ON `voter`.`House_ID`=`household`.`id` 
WHERE `CT` = '5' 
AND `Precnum` = 'CTY3' 
AND `Last_Name` LIKE '%Cumbee%' 
AND `First_Name` LIKE '%John%' 
ORDER BY `Last_Name` ASC 
LIMIT 30 

risposta

122

probabilmente sarei utilizzare Collega una sinistra, che restituirà le righe, anche se non c'è alcuna corrispondenza, e quindi è possibile selezionare solo le righe con alcuna corrispondenza con controllando per NULL.

Quindi, qualcosa di simile:

SELECT V.* 
FROM voter V LEFT JOIN elimination E ON V.id = E.voter_id 
WHERE E.voter_id IS NULL 

Se questo è più o meno efficiente rispetto all'utilizzo di una sottoquery dipende ottimizzazione, indici, se la sua possibile avere più di una dell'eliminazione per elettore, ecc

+8

+1 restituisce più velocemente delle query secondarie – ravi404

+1

+1 molto più veloce su alto carico, quindi sottocommissioni + se U può fare JOINs anziché subquery - basta fare JOINs sono molto più semplici per analizzatore. Un altro esempio utile, U potrebbe voler ottenere risultato se ci sono alcune righe in una tabella di destra o se non ce ne sono nessuno: 'SELEZIONA V. * DALL'elettore V ELIMINAZIONE SINISTRA UNISCIATA E ON V.id = E.voter_id O E .voter_id IS NULL' ex .: se U non vuole memorizzare tutti i record nella tabella di destra per ogni riga da sinistra. –

4

userei un 'dove non esiste' - esattamente come lei suggerisce nel titolo:

SELECT `voter`.`ID`, `voter`.`Last_Name`, `voter`.`First_Name`, 
     `voter`.`Middle_Name`, `voter`.`Age`, `voter`.`Sex`, 
     `voter`.`Party`, `voter`.`Demo`, `voter`.`PV`, 
     `household`.`Address`, `household`.`City`, `household`.`Zip` 
FROM (`voter`) 
JOIN `household` ON `voter`.`House_ID`=`household`.`id` 
WHERE `CT` = '5' 
AND `Precnum` = 'CTY3' 
AND `Last_Name` LIKE '%Cumbee%' 
AND `First_Name` LIKE '%John%' 

AND NOT EXISTS (
    SELECT * FROM `elimination` 
    WHERE `elimination`.`voter_id` = `voter`.`ID` 
) 

ORDER BY `Last_Name` ASC 
LIMIT 30 

quello può essere leggermente più veloce di fare una sinistra join (ovviamente, a seconda i tuoi indici, cardinalità delle tue tabelle, ecc.) ed è quasi certamente molto più veloce di rispetto all'utilizzo di IN.

+0

Grazie per quello - è stato decisamente più veloce per me. – spidie

15
+2

Conclusione di questo articolo: "Ecco perché il modo migliore per cercare valori mancanti in MySQL è usare LEFT JOIN/IS NULL o NOT IN piuttosto che NOT EXISTS." – marcovtwout

+3

link only answer = bad – Andrew

+0

Non correlato, tuttavia, ma un framework Alla mia sorpresa (Laravel) genera la query NON ESISTA quando si eseguono le query whereDoesntHave – Tebe

1

ci sono tre possibili modi per farlo.

  1. Opzione
 
     SELECT lt.* FROM table_left l 
     LEFT JOIN 
      table_right r 
     ON  rt.value = lt.value 
     WHERE rt.value IS NULL 
  1. Opzione
 
     SELECT lt.* FROM table_left l 
     WHERE lt.value NOT IN 
     (
     SELECT value 
     FROM table_right r 
     ) 
  1. Opzione
 
     SELECT lt.* FROM table_left l 
     WHERE NOT EXISTS 
     (
     SELECT NULL 
     FROM table_right r 
     WHERE rt.value = lt.value 
     )