[RESOLU] Extraire table mysql pour copier avec modif dans une autre

Eléphanteau du PHP | 34 Messages

12 déc. 2012, 22:00

Bonjour à tous,

J'ai une table mis dans le format suivant:
ENSEMBLE, Elément, Bt1, Bt2, Bt3....., Bt300

Bt1 à Bt300 sont des bâtiments (mais il n'y en a pas 300 mais environ 100 c'est juste leurs noms), chaque colonne bâtiment contient le nombre d'élément. Ce qui donne par exemple ceci
Image

Je voudrais copier cette table et l'insérer dans une autre (inventaire) qui est dans le format suivant:
type_ensemble, element, nom_batiment, nombre

Soit ceci:
Image

Est-ce que quelqu'un sait comment est-ce que je peux faire?

Si oui comment?

Merci d'avance

Maxredphenix

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

12 déc. 2012, 23:02

salut,


première question : est ce qu'il y a beaucoup de donnée ? (pas la peine de faire un dev pour 10 lignes, même avec 300 champs).

sinon il te faut faire un script SQL pour le passage des données d'une table a l'autre.

quitte a refactorer la base il serais préférable de la modéliser correctement .

dans ce cas je verrais
- une table qui contient les descriptions des types d'ensemble
- une table qui contient les descriptions des éléments
- une table qui contient les descriptions des bâtiments
- une table qui contient les données que tu souhaite, elle sera constituées de références sur les 3 premières tables ainsi que les quantités.

ensuite le passage de la première structure à la seconde est "relativement" simple, voici l'algorythme

Sélection de toutes les lignes à transférer de l'ancienne table
pour chaque lignes
récupérer la clef primaire de l'ensemble s'il n'existe pas le créer
récupérer la clef primaire de l'élément, s'il n'existe pas le créer
pour chaque colonne de bâtiment
insérer une nouvelle dans la nouvelle table avec l'ensemble ET l'élément récupéré au dessus + l'id du batiment et
insérer une nouvelle dans la nouvelle table avec l'ensemble ET l'élément récupéré au dessus + l'id du batiment et la quantité dans la colonne courante
fin pour chaque
fin pour chaque

@+
Il en faut peu pour être heureux ......

Eléphanteau du PHP | 34 Messages

12 déc. 2012, 23:37

Bonsoir,

Merci pour ton aide.

La base est composé d'environ 250 lignes d'ou le fait que je préfère trouver un moyen de le faire automatiquement :D

Je vais regarder ta solution.

Sinon tu penses que c'est possible?

Encore merci et bonne soirée

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

12 déc. 2012, 23:44

Oui oui très possible tu a déjà l’algorithme un simple script sql te permet de le faire. c'est a faire sur le sgbd directement pas besoin de le faire avec un autre langage ;)

inspire toi des procédure stockée pour cela http://dev.mysql.com/doc/refman/5.0/fr/ ... yntax.html

la première boucle est le traitement du curseur qui fait le 1er select.
La seconde boucle c'est sur le résultat pour éviter de taper les 100 champs de batiment ;)

@+
Il en faut peu pour être heureux ......

Eléphanteau du PHP | 34 Messages

13 déc. 2012, 09:59

Bonjour,

Encore une fois merci pour ta réponse.

Je vais regarder cela en rentrant du boulot.

Je te tiens au courant en cas de problème (enfin si tu le veux bien)

Bonne journée

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

13 déc. 2012, 23:14

Je suis loin d'être seul sur ce forum d'autre peuvent te répondre aussi ;)


@+
Il en faut peu pour être heureux ......

Eléphanteau du PHP | 34 Messages

15 déc. 2012, 10:32

Bonjour,

J'ai regarder pas mal de tuto, mais j'avoue que c'est pas si simple que ça, j'ai un peu de mal la :(

En fait, il faudrait que je fasse un select de toute ma bdd: SELECT * FROM table2
Je détermine le nombre de ligne dans ma table.
Puis, la première boucle qui parcours chaque ligne de mon tableau (ENSEMBLE, Elément, Bt1, Bt2, Bt3....., Bt300)
....Ensuite la 2eme boucle qui parcours les colonnes que chaque ligne
........On enregistre l'ensemble, l'element, le nom de la colonne (batiment), le nombre contenu dans la colonne batiment dans ma 2eme table.
........On exécute cela pour chaque bâtiment de la ligne
....Fin de la 2
Fin de la boucle 1
On retourne faire la 2eme ligne etc.....

C'est un peu près ça? Et le tout est possible depuis Mysql?

Encore merci

Eléphanteau du PHP | 34 Messages

02 janv. 2013, 12:37

Bonjour et Bonne année bien sur... :D

Je viens te revoir car je n'arrive pas à faire ce fichu transfert d'une table à une autre.

J'avoue que j'ai un peu de mal avec les procédures stockées et leurs principes.

Pourrais-tu m'aider stp?

Merci d'avance

maxredphenix

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

03 janv. 2013, 10:49

salut,

qu'as tu fait jusqu’à maintenant ?

peux tu poster le ddl des deux tables ? (le cde SQL de création des tables).
et un jeux de données minimaliste pour tester (même si les données sont bidons c'est histoire d'avoir une base de travail.

sinon :
- A tu regardé les curseurs ? (ton premier select)
- Les requêtes préparées ? (coté perf c'est mieux pour ce que tu souhaite faire ;) )
- est ce que tu bloque sur un point précis
- Peux être redéfinir les règles de gestion pour ne pas se gourer :)

et bonne année à toi aussi ;)

@+
Il en faut peu pour être heureux ......

Eléphanteau du PHP | 34 Messages

03 janv. 2013, 18:56

Bonsoir,

Tout d'abord merci, logiquement ça va être une bonne année (on verra bien :wink: ). J'ai lu pas mal de tuto et fait quelques essaies mais rien de concluant. Du coup j'ai tenté de faire cela avec php en faisant une boucle de récupération de chaque ligne de la bdd puis serialisation du résultat et enfin extraction des valeurs pour insertion dans la bonne table mais ..... ça non plus c'est pas terrible :?

Sinon voila les 2 tables (en premier la bonne et en 2ème celle qui contient les données a récupérer)
CREATE TABLE IF NOT EXISTS `inventaire` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `element` varchar(45) COLLATE utf8_unicode_ci NOT NULL,
  `type_ensemble` varchar(45) COLLATE utf8_unicode_ci NOT NULL,
  `nom_batiment` varchar(45) COLLATE utf8_unicode_ci NOT NULL,
  `nombre` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `inventaire2` (
  `ENSEMBLE` varchar(50) DEFAULT NULL,
  `Element` varchar(50) DEFAULT NULL,
  `003` int(11) DEFAULT '0',
  `004` int(11) DEFAULT '0',
  `006` int(11) DEFAULT '0',
  `007` int(11) DEFAULT '0',
  `008` int(11) DEFAULT '0',
  `010` int(11) DEFAULT '0',
  `011` int(11) DEFAULT '0',
  `012` int(11) DEFAULT '0',
  `014` int(11) DEFAULT '0',
  `015` int(11) DEFAULT '0',
  `016` int(11) DEFAULT '0',
  `018` int(11) DEFAULT '0',
  `020` int(11) DEFAULT '0',
  `021` int(11) DEFAULT '0',
  `022` int(11) DEFAULT '0',
  `022EXT` int(11) DEFAULT '0',
  `024` int(11) DEFAULT '0',
  `026` int(11) DEFAULT '0',
  `030` int(11) DEFAULT '0',
  `031` int(11) DEFAULT '0',
  `034` int(11) DEFAULT '0',
  `035` int(11) DEFAULT '0',
  `036` int(11) DEFAULT '0',
  `039` int(11) DEFAULT '0',
  `051` int(11) DEFAULT '0',
  `055` int(11) DEFAULT '0',
  `056` int(11) DEFAULT '0',
  `057` int(11) DEFAULT '0',
  `058` int(11) DEFAULT '0',
  `060` int(11) DEFAULT '0',
  `061` int(11) DEFAULT '0',
  `063` int(11) DEFAULT '0',
  `065` int(11) DEFAULT '0',
  `090` int(11) DEFAULT '0',
  `092` int(11) DEFAULT '0',
  `100` int(11) DEFAULT '0',
  `101` int(11) DEFAULT '0',
  `102` int(11) DEFAULT '0',
  `102EXT` int(11) DEFAULT '0',
  `104` int(11) DEFAULT '0',
  `105` int(11) DEFAULT '0',
  `106` int(11) DEFAULT '0',
  `107` int(11) DEFAULT '0',
  `109` int(11) DEFAULT '0',
  `110` int(11) DEFAULT '0',
  `111` int(11) DEFAULT '0',
  `112` int(11) DEFAULT '0',
  `113` int(11) DEFAULT '0',
  `114` int(11) DEFAULT '0',
  `115` int(11) DEFAULT '0',
  `116` int(11) DEFAULT '0',
  `117` int(11) DEFAULT '0',
  `118` int(11) DEFAULT '0',
  `119` int(11) DEFAULT '0',
  `120` int(11) DEFAULT '0',
  `121` int(11) DEFAULT '0',
  `122` int(11) DEFAULT '0',
  `123` int(11) DEFAULT '0',
  `124` int(11) DEFAULT '0',
  `125` int(11) DEFAULT '0',
  `126` int(11) DEFAULT '0',
  `127` int(11) DEFAULT '0',
  `128` int(11) DEFAULT '0',
  `129` int(11) DEFAULT '0',
  `130` int(11) DEFAULT '0',
  `131` int(11) DEFAULT '0',
  `132` int(11) DEFAULT '0',
  `134` int(11) DEFAULT '0',
  `135` int(11) DEFAULT '0',
  `136` int(11) DEFAULT '0',
  `137` int(11) DEFAULT '0',
  `138` int(11) DEFAULT '0',
  `140` int(11) DEFAULT '0',
  `141` int(11) DEFAULT '0',
  `142` int(11) DEFAULT '0',
  `143` int(11) DEFAULT '0',
  `145` int(11) DEFAULT '0',
  `147` int(11) DEFAULT '0',
  `148` int(11) DEFAULT '0',
  `149` int(11) DEFAULT '0',
  `150` int(11) DEFAULT '0',
  `151` int(11) DEFAULT '0',
  `152` int(11) DEFAULT '0',
  `154` int(11) DEFAULT '0',
  `155` int(11) DEFAULT '0',
  `156` int(11) DEFAULT '0',
  `157` int(11) DEFAULT '0',
  `159` int(11) DEFAULT '0',
  `162` int(11) DEFAULT '0',
  `163` int(11) DEFAULT '0',
  `168` int(11) DEFAULT '0',
  `169` int(11) DEFAULT '0',
  `171` int(11) DEFAULT '0',
  `172` int(11) DEFAULT '0',
  `173` int(11) DEFAULT '0',
  `174` int(11) DEFAULT '0',
  `177` int(11) DEFAULT '0',
  `180` int(11) DEFAULT '0',
  `181` int(11) DEFAULT '0',
  `187` int(11) DEFAULT '0',
  `188` int(11) DEFAULT '0',
  `191` int(11) DEFAULT '0',
  `193` int(11) DEFAULT '0',
  `194` int(11) DEFAULT '0',
  `195` int(11) DEFAULT '0',
  `196` int(11) DEFAULT '0',
  `200` int(11) DEFAULT '0',
  `202` int(11) DEFAULT '0',
  `223` int(11) DEFAULT '0',
  `224` int(11) DEFAULT '0',
  `234` int(11) DEFAULT '0',
  `416` int(11) DEFAULT '0',
  `458` int(11) DEFAULT '0',
  `720` int(11) DEFAULT '0',
  `723` int(11) DEFAULT '0',
  `724` int(11) DEFAULT '0',
  `730` int(11) DEFAULT '0',
  `Bt VIE` int(11) DEFAULT '0',
  `175` int(11) DEFAULT '0'
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Voila un exemple bibon d'enregistrement:
INSERT INTO `inventaire2` (`ENSEMBLE`, `Element`, `003`, `004`, `006`, `007`, `008`, `010`, `011`, `012`, `014`, `015`, `016`, `018`, `020`, `021`, `022`, `022EXT`, `024`, `026`, `030`, `031`, `034`, `035`, `036`, `039`, `051`, `055`, `056`, `057`, `058`, `060`, `061`, `063`, `065`, `090`, `092`, `100`, `101`, `102`, `102EXT`, `104`, `105`, `106`, `107`, `109`, `110`, `111`, `112`, `113`, `114`, `115`, `116`, `117`, `118`, `119`, `120`, `121`, `122`, `123`, `124`, `125`, `126`, `127`, `128`, `129`, `130`, `131`, `132`, `134`, `135`, `136`, `137`, `138`, `140`, `141`, `142`, `143`, `145`, `147`, `148`, `149`, `150`, `151`, `152`, `154`, `155`, `156`, `157`, `159`, `162`, `163`, `168`, `169`, `171`, `172`, `173`, `174`, `177`, `180`, `181`, `187`, `188`, `191`, `193`, `194`, `195`, `196`, `200`, `202`, `223`, `224`, `234`, `416`, `458`, `720`, `723`, `724`, `730`, `Bt VIE`, `175`) VALUES
('Television', 'samsung', 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 36, 4, 0, 2, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 15, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
('Television', 'lg', 0, 1, 1, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 1, 13, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
J'ai regarder divers sites pour les requêtes préparées, c'est là que j'ai appris que les banques utilisaient ce principe pour plus de sécurité, mais j'avoue que j'ai eu un peu de mal (peut-être à cause des fêtes, le cerveau ne voulait pas :D )


En tout cas je te remercie de bien vouloir m'aider et t'en remercie encore une fois.

Bonne soirée.

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

05 janv. 2013, 01:19

yop,


coté SQL, c'est galère MySQL est un poil à la rue (à coté d'oracle dont j'ai plus l'habitude sur le sujet).

du coup je te l'ai fait en php rapido.
Le code ne fait pas d'insertion si le nombre est zéro.
Cela évite d'encombrer la base pour rien :)
<?php
try {
	$pdo = new PDO('mysql:host=localhost;dbname=test', 'root');
	$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
	$pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_OBJ);
	$pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
	$pdo->setAttribute (\PDO::ATTR_CASE, \PDO::CASE_LOWER);
	$pdo->exec('SET NAMES \'utf8\'');
	$pdo->exec('set lc_time_names=\'FR_fr\'');
	$sql = 'select * from inventaire2';
	$select = $pdo->query($sql);
	$preparedInsert = $pdo->prepare('insert into inventaire
			(element,type_ensemble,nom_batiment,nombre) values
			(:elem,:type, :bat, :nb)');
	$i = 0;
	while($data =  $select->fetch(PDO::FETCH_OBJ)){
		foreach ($data as $field => $value){
			if(strtolower($field) == 'ensemble' || strtolower($field) == 'ENSEMBLE'){
				continue;
			}
			else {
				if( intval($value) !== 0) {
					$preparedInsert->bindValue('elem', $data->element);
					$preparedInsert->bindValue('type', $data->ensemble);
					$preparedInsert->bindValue('bat', $field);
					$preparedInsert->bindValue('nb', $value, PDO::PARAM_INT);
					$preparedInsert->execute();
					$i++;
				}
			}
		}
	}
	$select->closeCursor();
	echo '<p style="border: 1px solid green;">Il y a eu '.$i.' insertion(s)</p>';
}catch (Exception $e){
	echo 'Erreur SQL : '.$e->getMessage(),'<br /><pre>',$e->getTraceAsString(),'</pre>';
}
Pour infos, en partant sur quelque chose d'un poil plus normés.
le MCD de base : Image
les tables correspondantes :
CREATE TABLE materiel(
        idMateriel       int(11) Auto_increment  NOT NULL ,
        description      Varchar(50) NOT NULL ,
        idmarque int NOT NULL ,
        PRIMARY KEY (idMateriel)
)ENGINE=InnoDB;

CREATE TABLE marques(
        idmarque    int(11) Auto_increment  NOT NULL ,
        nom         Varchar(25) NOT NULL ,
        description Varchar(200),
        PRIMARY KEY (idmarque)
)ENGINE=InnoDB;

CREATE TABLE batiments(
        idbatiment  int(11) Auto_increment  NOT NULL ,
        nom         Varchar(20),
        description Varchar(200),
        PRIMARY KEY (idbatiment)
)ENGINE=InnoDB;

CREATE TABLE contenir(
        quantite             Int,
        idMateriel  Int NOT NULL ,
        idbatiment Int NOT NULL ,
        PRIMARY KEY (idMateriel,idbatiment)
)ENGINE=InnoDB;

ALTER TABLE materiel ADD CONSTRAINT FK_materiel_idmarque_marques FOREIGN KEY (idmarque) REFERENCES marques(idmarque);
ALTER TABLE contenir ADD CONSTRAINT FK_contenir_idMateriel_materiel FOREIGN KEY (idMateriel) REFERENCES materiel(idMateriel);
ALTER TABLE contenir ADD CONSTRAINT FK_contenir_idbatiment_batiments FOREIGN KEY (idbatiment) REFERENCES batiments(idbatiment);
Et après le traitement est un poil plus complexe mais du même style que celui donné plus haut.


@+
Il en faut peu pour être heureux ......

Eléphanteau du PHP | 34 Messages

05 janv. 2013, 11:18

Bonjour,

Je tiens à te remercier pour ta réponse et pour ce magnifique code php qui fonctionne.....parfaitement bien :D et en plus, j'y ai pensé plus tard mais le fait que cela ne prenne pas les 0 m'arrange énormément.

Pour la structure de mes tables, justement j'étais en train de revoir un peu cette partie inventaire parce qu'elle est trop simple et pas assez "détaillé" (on va dire).

Je vais voir pour adapter ce que je pensais faire avec les éléments que tu m'as donné.

En tout cas, encore merci de ton aide, je t'avoue que cela m'évite de recréer manuellement chaque élément (en tout cela m'a fait 1410 lignes, ça aurait été long.. :( )

A bientôt