Trop de tables; MySQL peut utiliser seulement 61 tables dans une jointure
Quelle est la meilleure façon d'exporter des données à partir de plusieurs tables dans MySQL. Je suis fondamentalement de travailler avec les détails du produit. Dire qu'un produit a 150 attributs de données. Comment puis-je exporter en une seule ligne, puis de les exporter vers un fichier plat au format CSV ou délimités par des tabulations format.
Avoir d'erreur beaucoup Trop de tables; MySQL peut utiliser seulement 61 tables dans une jointure
/**** Get Resultset *****/
$rs = mysql_query($sql);
/**** End of Get Resultset *****/
$objProfileHistory->addHistory($this->profile_id, "Loaded ". mysql_num_rows($rs)." records");
$this->runQuery($sql);
$this->exportToCSV();
/**
* getAttributeDetails
*/
function getAttributeDetails(){
global $dbObj, $profile;
$base_table = "catalog_product_entity";
$select = array();
$tables = array();
$i = 0;
$profile->showLog("Start fields mapping", "success");
if( is_array($this->attributes_in_db) && sizeof($this->attributes_in_db) > 0 ){
$arr = implode("','", $this->attributes_in_db);
$sql = "select attribute_id, attribute_code, backend_type, frontend_input
from eav_attribute
where attribute_code in ('".$arr."')
and entity_type_id =
(select entity_type_id
from eav_entity_type
where entity_type_code = 'catalog_product')";
$rs = $dbObj->customqry($sql);
if( $rs ){
while( $row = mysql_fetch_assoc( $rs ) ){
$backend_type = $row["backend_type"];
$attribut_code = $row["attribute_code"];
$attribute_id = $row["attribute_id"];
$frontend_input = $row["frontend_input"];
switch( $backend_type ){
case "text":
$where[] = $base_table."_".$backend_type."".$i.".attribute_id=".$attribute_id;
$and[] = $base_table.".entity_id=".$base_table."_".$backend_type."".$i.".entity_id";
$select[] = $base_table."_".$backend_type."".$i.".value as ".$attribut_code;
$tables[] = $base_table."_".$backend_type." as ".$base_table."_".$backend_type."".$i;
break;
case "decimal":
$where[] = $base_table."_".$backend_type."".$i.".attribute_id=".$attribute_id;
$and[] = $base_table.".entity_id=".$base_table."_".$backend_type."".$i.".entity_id";
$select[] = $base_table."_".$backend_type."".$i.".value as ".$attribut_code;
$tables[] = $base_table."_".$backend_type." as ".$base_table."_".$backend_type."".$i;
break;
case "static":
$where[] = $base_table."".$i.".entity_id=".$base_table.".entity_id";
$and[] = $base_table.".entity_id=".$base_table."".$i.".entity_id";
$select[] = $base_table."".$i.".".$attribut_code." as ".$attribut_code;
$tables[] = $base_table." as ".$base_table."".$i;
break;
case "int":
if( $attribut_code == "tax_class_id" && $frontend_input == "select" ){
$where[] = "tax_class{$i}.class_id=(select ".$base_table."_".$backend_type."".$i.".value from ".$base_table."_".$backend_type." as ".$base_table."_".$backend_type."".$i." where ".$base_table."_".$backend_type."".$i.".attribute_id=".$attribute_id." and ".$base_table."_".$backend_type."".$i.".entity_id=".$base_table.".entity_id limit 1))";
$and[] = "";
$select[] = "tax_class{$i}.class_name as {$attribut_code}";
$tables[] = "tax_class as tax_class{$i}";
} else if( $frontend_input == "select" ){
$where[] = "eav_attribute_option_value{$i}.option_id=(select ".$base_table."_".$backend_type."".$i.".value from ".$base_table."_".$backend_type." as ".$base_table."_".$backend_type."".$i." where ".$base_table."_".$backend_type."".$i.".attribute_id=".$attribute_id." and ".$base_table."_".$backend_type."".$i.".entity_id=".$base_table.".entity_id limit 1))";
$and[] = "";
$select[] = "eav_attribute_option_value{$i}.value as {$attribut_code}";
$tables[] = "eav_attribute_option_value as eav_attribute_option_value{$i}";
} else {
$where[] = $base_table."_".$backend_type."".$i.".attribute_id=".$attribute_id;
$and[] = $base_table.".entity_id=".$base_table."_".$backend_type."".$i.".entity_id";
$select[] = $base_table."_".$backend_type."".$i.".value as ".$attribut_code;
$tables[] = $base_table."_".$backend_type." as ".$base_table."_".$backend_type."".$i;
}
break;
case "varchar":
$where[] = $base_table."_".$backend_type."".$i.".attribute_id=".$attribute_id;
$and[] = $base_table.".entity_id=".$base_table."_".$backend_type."".$i.".entity_id";
$select[] = $base_table."_".$backend_type."".$i.".value as ".$attribut_code;
$tables[] = $base_table."_".$backend_type." as ".$base_table."_".$backend_type."".$i;
break;
case "datetime":
$where[] = $base_table."_".$backend_type."".$i.".attribute_id=".$attribute_id;
$and[] = $base_table.".entity_id=".$base_table."_".$backend_type."".$i.".entity_id";
$select[] = $base_table."_".$backend_type."".$i.".value as ".$attribut_code;
$tables[] = $base_table."_".$backend_type." as ".$base_table."_".$backend_type."".$i;
break;
}//switch
$i++;
}//while
$sql = "select ".implode(",", $select)." from ".$base_table;
for($i=0; $i < sizeof($select); $i++){
$sql .= " left join ". $tables[$i] . " on (".$where[$i];//." and ".$and[$i].")";
if( strlen($and[$i]) > 0 ){
$sql .= " and ".$and[$i].")";
}
}//for
$sql .= " group by {$base_table}.entity_id ";
}//if
//echo $sql; exit;
return $sql;
}
//echo $sql;
//echo "<pre>";print_r($tables);print_r($select);print_r($where);print_r($and);
}//end function
/**
* runQuery
*/
function runQuery( $sql ){
global $dbObj, $profile;
if( $sql != "" ){
$rs = $dbObj->customqry( $sql );
$profile->showLog("Loaded ". mysql_num_rows($rs) ." records", "success");
if( $rs ){
$i = 0;
while( $row = mysql_fetch_assoc( $rs ) ){
$cnt = sizeof($this->attributes_in_db);
for($j=0; $j < $cnt; $j++){
$db_key = $this->attributes_in_db[$j];
$file_key = $this->attributes_in_file[$j];
$this->export_data[$i][$db_key] = $row[$db_key];
}
$i++;
}//while
}
}//if
}//end function
/**
* exportToCSV
*/
function exportToCSV(){
global $smarty, $objProfileHistory, $profile;
//$newFileName = $smarty->root_dir."/export/".$this->filename; //file name that you want to create
$cnt = sizeof($this->var_array);
for($i=0; $i < $cnt; $i++){
extract($this->var_array[$i]);
}//for
if( $delimiter = "\t" ){
$delimiter = "\t";//$delimiter;
}
if( strlen($filename) < 1 ){
$filename = time().".csv";
}
// echo "<pre>";
// print_r($this->action_array);
// print_r($this->var_array);
// print_r($this->map_array);
// exit;
# add amazon headers
if( $this->action_array[0]['type'] == 'header' ){
// $template_type = $this->var_array[0]['template_type'];
// $version = $this->var_array[0]['version'];
// $status_message = $this->var_array[0]['status_message'];
$sStr = "TemplateType=".$template_type."{$delimiter}{$delimiter}Version=".$version."{$delimiter}{$delimiter}{$status_message}";
$sStr .= "� ��\n"; //to seprate every record
}
$export_path = $path;
$x_path = $profile->createDir( $export_path );
$newFileName = $x_path ."/". $filename;
$fpWrite = fopen($newFileName, "w"); // open file as writable
# create header
$cnt_header = sizeof($this->attributes_in_file);
for( $i=0; $i < $cnt_header; $i++){
$sStr .= $deli . $this->attributes_in_file[$i];
$deli = $delimiter;
}//for
$sStr .= "� ��\n"; //to seprate every record
# attach data
$cnt_row = sizeof($this->export_data);
for( $i=0; $i < $cnt_row; $i++ ){
$sStr .= $saperator;
$newdeli = "";
for($j=0; $j < $cnt_header; $j++){
$key = $this->attributes_in_db[$j];
$sku = $this->export_data[$i]["sku"];
QUELLE EST LA MEILLEURE FAÇON D'EXPORTER DES DONNÉES À PARTIR DE PLUSIEURS TABLES DANS MYSQL. M ESSENTIELLEMENT TRAVAILLER AVEC LES DÉTAILS DU PRODUIT. DIRE qu'UN PRODUIT A 150 attributs de données comment puis-je exporter en une seule ligne, puis de les exporter vers un fichier plat au format csv ou délimités par des tabulations format.
Le temps de repenser à cette requête. De joindre plus de l'ordre de 7 tables est une performance killer pour toute base de données. Avez-vous jamais exécuter cette requête n'importe où?
Le temps de repenser à cette requête. De joindre plus de l'ordre de 7 tables est une performance killer pour toute base de données. Avez-vous jamais exécuter cette requête n'importe où?
OriginalL'auteur user204245 | 2009-11-06
Vous devez vous connecter pour publier un commentaire.
Vous utilisez un VAE de conception, et d'essayer de re-construction d'une seule ligne à partir d'un nombre variable d'attributs. Cela souligne l'une des nombreuses mines vous rencontrerez à l'aide de l'EAV de la conception: il y a une limite sur le nombre de jointures, vous pouvez le faire en une seule requête SQL.
En particulier dans MySQL, il y a une limite dure, comme vous l'avez trouvé. Mais même dans d'autres SGBD, il y a une limite effective, car le coût de jointures est géométrique à l'égard du nombre de tables.
Si vous utilisez EAV, ne pas essayer de re-construire une ligne de SQL comme si vous aviez un classique de conception de base de données. Au lieu de cela, chercher les attributs de lignes, triés par l'id de l'entité. Ensuite post-processus dans le code de votre application. Cela signifie que vous ne pouvez pas vider les données en une seule étape, vous devez écrire le code d'une boucle sur l'attribut lignes, et la réforme de chaque ligne de données avant de vous pouvez de sortie.
VAE n'est pas une pratique de conception de base de données. Il y a beaucoup de coûteux inconvénients à l'utilisation, et vous avez juste frappé l'un d'eux.
Voir http://www.simple-talk.com/opinion/opinion-pieces/bad-carma/ pour une grande histoire sur la façon d'utiliser EAV condamné une entreprise.
Et aussi voir http://en.wikipedia.org/wiki/Inner-platform_effect parce que la VAE est un exemple de cet Anti-modèle.
Je comprends la nécessité de soutenir une dynamique d'un ensemble d'attributs par produit dans un catalogue. Mais EAV va tuer votre application. Voici ce que je fais pour soutenir les attributs dynamiques:
Définir une véritable colonne dans la table de base pour chaque attribut qui est commune à tous les types de produits. Nom du produit, le prix, la quantité en stock, etc. Travailler dur à imaginer les canonique produit entité de sorte que vous pouvez inclure autant d'attributs que possible dans ce jeu.
Définir encore une colonne de type
TEXT
pour tous les autres attributs de chaque type de produit. Les magasins de cette colonne comme Sérialisé LOB des attributs, quel que soit le format qui vous convient: XML, JSON, YAML, votre propre maison DSL, etc.Traiter cela comme une seule colonne dans vos requêtes SQL. Toute recherche, le tri et l'affichage que vous devez faire sur la base de ces attributs vous oblige à chercher de l'ensemble de la
TEXT
blob dans votre application désérialiser, et d'analyser les attributs à l'aide de code de l'application.OriginalL'auteur Bill Karwin
Si vous avez ce grand nombre d'attributs, je pense que c'est une base de données éparses, de sorte que vous avez beaucoup d'espace perdu.
Vous voudrez peut-être chercher à l'aide d'une Entité-Attribut-Valeur de la base de données au lieu de cela, si possible.
http://en.wikipedia.org/wiki/Entity-attribute-value_model
Ce que cela vous permet d'acheter est un moyen de revoir la base de données, mais à ce qu'il soit plus extensible, et de réduire le nombre de tables dont vous avez besoin. Vous devriez être en mesure de descendre de 4 à 6 tables (2-3 tables entité avec leurs attributs). C'est un peu plus difficile de créer les requêtes que toutes les requêtes seront dynamiques, mais il permettra de simplifier votre exportation, et la maintenance de base de données devrait être plus simple.
Si vous devez utiliser ce schéma, vous pouvez créer plusieurs déclencheurs et puis vous pouvez appeler le déclencheur, ce qui est de joindre plusieurs tables, et ensuite faire votre requête, mais que vous allez prendre un énorme gain de performance.
Mise à JOUR:
Depuis un EAV table est utilisée, et que MySQL ne fait pas une fonction de pivot, vous pouvez lire la réponse à cette question:
Comment pivoter une base de données MySQL entité-attribut-valeur de schéma
Comment pivoter une base de données MySQL entité-attribut-valeur de schéma
Je vois que maintenant, wow.
OriginalL'auteur James Black
Si vous êtes à l'aide de la VAE et que vous souhaitez exporter un grand nombre d'attributs à la fois, le meilleur moyen est en fait d'utiliser plusieurs tables temporaires.
Chaque table temporaire ont la même colonne de la clé primaire. Puis me joindre à eux et de les exporter en csv.
Je ne sais pas si je veux faire un bien définis, par exemple, mais je vais essayer de faire un plan qui devrait rendre les choses plus claires.
1.) Obtenez votre liste d'attributs que vous souhaitez exporter. Vous allez utiliser leur attribute_ids dans la jointure de votre VAE attribute_values table.
2.) Séparer les attributs de sorte que vous n'aurez pas dépasser la jointure limite. Vous avez besoin de la table d'origine, et 1 table pour rejoindre, de sorte que vous pouvez avoir 60 attributs par table dans ce schéma.
3.) Créer "à plat" des tables temporaires pour chaque groupe d'attributs. Il serait quelque chose comme ça.
4.) Maintenant, vous avez les tables temporaires temp1, temp2, temp3, etc. Ils partagent tous la même clé primaire (produit_id et/ou product_sku par exemple).
En supposant que vous avez moins de 60 tables temporaires (ce qui serait absurde), vous pouvez maintenant rejoindre tous ceux et créer une table unique.
Dans mon système, je ne pense pas que j'ai dépassé les 3 tables temporaires et c'est plutôt pas mal.
5.) À l'exportation. Utilisation de MySQL fichier d'exportation pour créer un fichier CSV. L'envoyer à l'utilisateur avec PHP.
J'espère que ça aide.
Noter également que le processus ci-dessus s'exécute assez rapidement pour moi. La raison d'utiliser des tables temporaires est parce qu'ils seront supprimées automatiquement après utilisation, et parce que plusieurs utilisateurs peuvent exécuter le même type de processus sans interférer les uns avec les autres depuis les tables temporaires n'existent que pour l'utilisateur qui les a créés.
J'ai mis à jour ma réponse avec un aperçu de ce que je voudrais faire. Laissez-moi savoir si ça a du sens ou pas. Notez également que je suis en réalité à l'aide de cette idée et il est travaillé pour moi.
OriginalL'auteur Buttle Butkus