2016-04-21 3 views
0

ContraintesMySQL joindre des tables avec des valeurs en double multiples Rejoindre colonnes

  • Les tables sont dénormalisés
  • Impossible d'utiliser la sous-requête

Tables

Nom: Emplacements

+-----------+-------------+------+-----+---------+----------------+ 
| Field  | Type  | Null | Key | Default | Extra   | 
+-----------+-------------+------+-----+---------+----------------+ 
| id  | int(11)  | NO | PRI | 0  | auto_increment | 
| zip_code | varchar(12) | NO |  |   |    | 
| city  | varchar(64) | NO | MUL |   |    | 
| county | varchar(64) | NO | MUL |   |    | 
| state  | varchar(64) | NO | MUL |   |    | 
| info  | varchar(99) | NO |  |   |    | 
+-----------+-------------+------+-----+---------+----------------+ 

Nom: Adresses

+------------------+---------------+------+-----+-------+-----------+ 
| Field   | Type   | Null | Key | Default | Extra | 
+------------------+---------------+------+-----+-----------+-------+ 
| id    | int(11)  | NO | PRI | 0   |  | 
| address_one  | varchar(255) | NO |  |   |  | 
| address_two  | varchar(255) | NO |  |   |  | 
| city    | varchar(30) | NO | MUL |   |  | 
| state   | varchar(25) | NO | MUL |   |  | 
| zip_code   | varchar(7) | NO | MUL | NULL  |  | 
| country_code  | char(2)  | YES |  |   |  | 
+------------------+---------------+------+-----+-----------+-------+ 

Le problème

  • Tables Emplacements et Adresses auront state dupliqués sur plusieurs lignes.
  • Les emplacements table a environ 100k lignes et le adresses table a environ 1M lignes.

La question

Je dois obtenir une liste unique de states avec leur info des Emplacements table où il y a au moins une adresse dans les adresses des tables pour toute la state respective .

Toute jointure que j'ai, sans utiliser de sous-requêtes, finit par prendre une éternité.

Quelle requête satisfera les Contraintes?

+0

Et pourquoi avez-vous de telles contraintes? Si c'est un problème de devoirs, il est poli de le décrire comme tel * explicitement *. –

+0

Pas un problème de devoirs. Essayait d'être forcé de croire que toute utilisation d'une sous-requête, y compris dans ce cas était un problème de performance.Je pense que la sous-requête est la bonne voie à suivre. – webish

+0

Cela sent comme une requête postée (et adressée) sur un autre forum. Si oui, lien croisé. –

Répondre

0

Vous pouvez utiliser:

SELECT state, info FROM locations LEFT JOIN addresses USING (state) WHERE address_one IS NOT NULL GROUP BY state; 

Cette requête ne pas utiliser une sous-requête.

+0

S'il y a plusieurs lignes avec le même état dans les deux tables, ce qui est le cas, cette requête correspond à TOUS et est extrêmement lente. – webish

+0

@webish, oups c'est correct. J'ai ajouté un GROUP BY à la fin pour ne faire que des états distincts. –

1

C'est un mythe que les sous-requêtes sont un problème de performance. Parfois ils le sont; parfois ils ne le sont pas. Il n'y a pas une telle règle simple.

Dans votre cas, je pourrais suggérer:

select l.* 
from (select distinct state, info 
     from locations l 
    ) l 
where exists (select 1 
       from addresses a 
       where a.state = l.state 
      ); 

Pour les performances, vous voulez des indices sur locations(state, info) et addresses(state).

Il existe deux sous-requêtes, mais avec des index appropriés, cela peut être le moyen le plus rapide d'exprimer cette logique.