2010-09-03 12 views
2

J'essaie de trouver la meilleure approche pour une migration de données.Meilleure façon de migrer une table MySQL avec des dupes vers une autre table avec une contrainte UNIQUE

J'émigre des données (~ 8000 lignes) d'une table comme ceci:

CREATE TABLE location (
    location_id INT NOT NULL AUTO_INCREMENT UNIQUE PRIMARY KEY, 
    addr VARCHAR(1000) NOT NULL, 
    longitude FLOAT(11), 
    latitude FLOAT(11) 
) Engine = InnoDB, DEFAULT CHARSET=UTF8; 

à une table comme ceci:

CREATE TABLE location2 (
    location_id INT NOT NULL AUTO_INCREMENT UNIQUE PRIMARY KEY, 
    addr VARCHAR(255) NOT NULL UNIQUE, 
    longitude FLOAT(11), 
    latitude FLOAT(11) 
) Engine = InnoDB, DEFAULT CHARSET=UTF8; 

Il est important de ne pas préserver la clé primaire.

Les adresses de "location" sont dupliquées plusieurs fois. Dans la plupart des cas, avec la même latitude et la même longitude. Mais dans certains cas, il existe des lignes avec la même valeur pour addr mais DIFFERENT pour la latitude et la longitude.

La table location2 finale devrait avoir une entrée pour chaque entrée addr unique dans l'emplacement. Lorsqu'il y a plus d'une valeur possible pour la latitude/longitude, la dernière valeur (le plus haut identifiant_de_localisation) doit être utilisée.

J'ai créé une procédure pour cela, mais elle n'aime pas les lignes où addr est identique mais la latitude/longitude est différente.

DROP PROCEDURE IF EXISTS migratelocation; 
DELIMITER $$ 
CREATE PROCEDURE migratelocation() 
BEGIN 
    DECLARE done INT DEFAULT 0; 
    DECLARE a VARCHAR(255); 
    DECLARE b, c FLOAT(11); 
    DECLARE cur CURSOR FOR SELECT DISTINCT addr, latitude, longitude FROM location; 
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; 
    OPEN cur; 
    REPEAT 
     FETCH cur INTO a, b, c; 
     IF NOT done THEN 
      INSERT INTO location2 (addr, latitude, longitude) VALUES (a, b, c); 
     END IF; 
    UNTIL done END REPEAT; 
    CLOSE cur; 
END $$ 
DELIMITER ; 
CALL migratelocation(); 

Existe-t-il un bon moyen de le faire? Je continue à vouloir abandonner et écrire un peu de prog PHP pour le faire mais je préfère apprendre la bonne façon SQL si je le peux.

Peut-être j'ai juste besoin de trouver le bon SELECT de la première table et je peux utiliser:

INSERT INTO location2 SELECT ... ; 

pour migrer les données.

Merci!

Répondre

4

Vous pouvez utiliser directement IGNORE INSERT, ou REPLACE - Je suppose qu'il s'agit d'un processus unique, ou au moins un processus dans lequel la performance n'est pas une considération majeure.

Dans ce cas, le record avec la plus haute gagne LOCATION_ID:

INSERT IGNORE 
INTO location2 
SELECT * 
FROM location 
ORDER BY 
     location_id DESC 

Les enregistrements suivants wit la même valeur de clé primaire sont simplement mis au rebut par l'insert.

Vous auriez besoin du mode SQL strict pour être désactivé, sinon la troncature du champ ADR donnera des erreurs.

+0

Cela fait exactement ce que dit l'homme. Merci beaucoup. –