从MySQL中的多个表导出数据的最佳方法是什么。我基本上是在处理产品详细信息。假设一个产品具有150个数据属性。如何将其导出为一行,然后将其导出为CSV或制表符分隔格式的平面文件。
错误越来越多 MySQL在一个联接中只能使用61个表
/**** 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"];
您正在使用EAV设计,并尝试根据可变数量的属性来重构单行。这指出了使用EAV设计将遇到的众多地雷之一:在单个SQL查询中可以执行的连接数量有实际限制。
正如您所发现的,尤其是在MySQL中-有一个硬限制。但是,即使在其他RDBMS品牌中,也存在有效的限制,因为联接的成本相对于表的数量是几何的。
如果您使用EAV, 请不要 像在常规数据库设计中 那样尝试在SQL中重新构造行
。取而代之的是,将属性按行获取,并按实体ID排序。然后在您的应用程序代码中对它们进行后处理。这确实意味着您不能一步一步地转储数据-
您必须编写代码以遍历属性行,并在输出数据之前对每一行数据进行重新格式化。
EAV不是方便的数据库设计。使用它有许多昂贵的缺点,而您已经遇到了其中之一。
有关使用EAV如何注定一个企业的伟大故事,请参见http://www.simple-talk.com/opinion/opinion-
pieces/bad-carma/
。
另外,请参阅http://en.wikipedia.org/wiki/Inner-
platform_effect,因为EAV是此反模式的一个示例。
我了解需要支持目录中每个产品的动态属性集。但是,EAV会杀死您的应用程序。这是我支持动态属性的操作:
在基本表中为所有产品类型共有的每个属性定义一个实列。产品名称,价格,库存数量等。努力想象规范的 产品 实体,以便您可以在此集中包含尽可能多的属性。
TEXT
为每种给定产品类型的所有其他属性定义一个类型列。以适合您的格式存储在此列中,作为属性的序列化LOB:XML,JSON,YAML,您自己的自制DSL等。
将此视为SQL查询中的单个列。根据这些属性进行的任何搜索,排序或显示操作,都需要将整个TEXT
Blob
提取到应用程序中,以对它进行反序列化,然后使用应用程序代码分析属性。
问题内容: 我有以下查询: 所以我正在使用并抓住。所以现在,我要获取该image_id并将其从图像表中转换成。 如何将其添加到查询中? 问题答案: 您可以简单地添加另一个联接,如下所示: 但是请注意,由于它是一个,如果您的消息中没有图像,则将跳过整个行。如果可能的话,您可能需要执行一次操作,该操作将仅在存在一个仪表板消息的情况下返回所有仪表板消息和一个image_filename(否则,您将获得n
问题内容: 我有一个网站,该网站将选项存储在多个表中,并根据单个页面提取所有相关选项。此刻,我结束了这样的查询:。这确实不是一个坏问题,但是我必须逐个遍历每个选择结果。 我想将所有这些提取到单个网格中,然后执行类似的操作 如果使用类似的查询,则会结束所有可能的行组合(第一个foo第一栏,第二个foo第二栏,第二个foo第一栏,第二个foo第二栏等)。 有没有一种方法可以执行这样的选择,并且每个元素
我正在尝试使用多个条件连接两个表。由于第二个联接条件,以下查询不起作用。
问题内容: 我有一个NewsStories表格,剩下一些相关表格。每个新闻故事可以具有多个图像,类别和地址。因此查询实质上是: 通常每个故事有一些图像和地址,以及1或2个类别。NewsStories表包含大约10,000条文章。 问题在于性能相当慢(大约15-20秒,尽管它的确变化很大,有时甚至低至5秒)。 我想知道是否有更好的方法来组织查询以加快查询速度(我对SQL还是很陌生)。 尤其是,给定故
问题内容: 我只是试图通过添加滚动视图来增加在此布局中滚动的能力,但是每次尝试加载布局时,我都会收到一条错误消息,指出“ java.lang.IllegalStateException:ScrollView只能容纳一个直接子代”,并且我不确定为什么。 任何建议,不胜感激。 资源: 编辑(响应CodeMagic的回答) 问题答案: 正如错误所言 将s 包裹在a 的内部,因此只有as作为直接子代。 来
我想添加表示来自其他表的计数的列。 我有三张桌子。 消息 主题 STARS_GIVED 我想以: 主题回顾 所以基本上,我想附上3列唯一值的计数(每个主题中给出的星数,在主题中有消息的唯一用户,以及每个主题中唯一消息的数量)。 我希望最终能够对类别进行筛选(看看两列)。 此外,我希望最终按我加入的计数排序。例如,我将有一个按钮,按“星星的数目”按升序排序,或按“用户的数目”按降序排序,等等。 我试