繁体   English   中英

我可以使用 php function 来执行相当于 mySQL 左连接的操作吗?

[英]Can I use a php function to perform the equivalent of a mySQL left join?

我遇到的问题是使用下面的当前 function 加载时间太长。 正在连接的两个表各包含数千行。 保存表连接的特定 function 是下面 model 部分中的&getFields() function。

我在想我可能有一个 function 最初检查请求是编辑还是添加新的,然后处理仅在编辑查询上分离表连接(不知道如何完成此操作)。


从页面初始页面调用- 使用 html 表单和 post 方法

if(count($this->fields)){
    for($i=0;$ifields);$i++){
        $field =& $this->fields[$i];
        $se = $field->section;
        $ti = $field->title;
        $ft = $field->type;
        $na = $field->name;
        $fva = $field->field_value;
        $nu = $field->unit;
        switch($se){
            case 'header' :
                        echo 'input type="blah...


Controller 将流量定向到 Model

function __construct() {
    parent::__construct();
    $this->registerTask('add','edit');
    JRequest::setVar('view','cpanel');
}

function edit() {
    JRequest::setVar('layout','form');
    parent::display();
}

function save() {
    $model = $this->getModel('cpanel');
    $msg = $model->store();
    $link = ;
    $this->setRedirect($link, $msg);
}


拥有实际功能的Model

function __construct() {
    parent::__construct();
    global $mainframe;

    $array = JRequest::getVar('cid',  0, '', 'array');
    $this->setId((int)$array[0]);
}

function setId($id) {
    // Set id and wipe data
    $this->_id      = $id;
    $this->_data    = null;
}

function &getItem() {
    if(empty($this->_data)) {
        $query = ' SELECT * FROM #__directory_entry WHERE id = '.$this->_id;
        $this->_db->setQuery( $query );
        $this->_data = $this->_db->loadObject();
    }
    if(!$this->_data)   {
        $session =& JFactory::getSession();
        $post = $session->get('post');
        $this->_data->id = 0;
        $this->_data->title = isset($post['title'])?$post['title']:null;
    }
    return $this->_data;
}

function &getFields() {
    $query = 'select f.*, ef.field_value from #__directory_field as f left join
#__directory_enf as ef on (f.id = ef.field_id and ef.entry_id = '.$this->_id.') where
f.published = 1 order by f.ordering asc';
$this->_db->setQuery( $query ); $fields = $this->_db->loadObjectList(); $session =& JFactory::getSession(); if($session->has('post') and !$this->_id) { $post = $session->get('post'); for($i=0;$ifield_value = isset($post['field_'.$fields[$i]->name])?$post['field_'.$fields[$i]->name]:null; } return $fields; } function store() { // Check for request forgeries JRequest::checkToken() or jexit( JText::_('Invalid Token') ); $post = JRequest::get( 'post' ); $session =& JFactory::getSession(); $session->set('post', $post); if($post["title"] == "") return JText::_('Please enter the title'); $query = 'select * from #__directory_field where published = 1'; $this->_db->setQuery( $query ); $fields = $this->_db->loadObjectList(); for($i=0;$irequired and $post['field_'.$fields[$i]->name] == "") return JText::_($fields[$i]->title . ' is required field and can not be left blank.'); } if(!$post["id"]) { $date =& JFactory::getDate(); $post['create_date'] = $date->toMySQL(); $post['ordering'] = 1; $query = 'select ordering from #__directory_entry order by ordering desc limit 1'; $this->_db->setQuery( $query ); $post['ordering'] += $this->_db->loadResult(); $post['published'] = 1; } $me =& JFactory::getUser(); JTable::addIncludePath(JPATH_ADMINISTRATOR.DS.'components'.DS.'com_joomd'.DS.'tables'); $row =& JTable::getInstance('entry', 'Table'); if (!$row->bind( $post )) return JText::_('Sorry some Error Occurred.'); if (!$row->store()) return $this->_db->getErrorMsg(); if(!$post['id']) { $post['id'] = $this->_db->insertid(); JRequest::setVar('id', $post['id']); $msg = JText::_('Entry successfully added!'); $query = 'insert into #__directory_enu (entry_id, user_id) values ('.$post['id'].', '.$me->id.')'; $this->_db->setQuery( $query ); $this->_db->query(); } else $msg = JText::_('Entry successfully Updated!'); $max_size = 10000000; jimport('joomla.filesystem.file'); $time = time(); for($i=0;$itype == "image") $allowed = array('.jpg', '.jpeg', '.gif', '.png'); elseif($field->type == "file") $allowed = array('.doc', '.docx', '.pdf', '.txt', '.exl', '.xls', '.xlsx', '.jpg', '.jpeg', '.gif', '.png', '.zip'); $flag = true; $query = 'select count(*) from #__directory_enf where entry_id = ' . $post["id"] .' and field_id = ' . $field->id; $this->_db->setQuery( $query ); $count = $this->_db->loadResult(); if($field->type == "image" or $field->type == "file") { $image = JRequest::getVar("field_".$field->name, null, 'FILES', 'array'); $image_name = str_replace(' ', '', JFile::makeSafe($image['name'])); $image_tmp = $image["tmp_name"]; if($image_name "") { $ext = strrchr($image_name, '.'); if(!in_array($ext, $allowed)) return sprintf(JText::_('File type for %s is not allowed.'), $field->title); if(filesize($image_tmp) > $max_size) return sprintf(JText::_('File size for %s exceeds the maximum file size.'), $field->title); if(move_uploaded_file($image_tmp, JPATH_SITE.'/files/'.$time.$image_name)) $post["field_".$field->name] = $time.$image_name; else return sprintf(JText::_('Sorry File for %s could not be uploaded.'), $field->title); } else $flag = false; } if($flag) { if($count) { $query = 'select id from #__directory_enf where entry_id = '.$post["id"].' and field_id = ' . $field->id; $this->_db->setQuery( $query ); $field_id = $this->_db->loadResult(); $update = new stdClass(); $update->id = $field_id; $update->field_value = $post["field_".$field->name]; $this->_db->updateObject('#__directory_enf', $update, 'id'); } else { $insert = new stdClass(); $insert->id = null; $insert->field_id = $field->id; $insert->entry_id = $post["id"]; $insert->field_value = $post["field_".$field->name]; $this->_db->insertObject('#__directory_enf', $insert, 'id'); } } } $session->clear('post'); return $msg; }

Left Join 是最快的方法,但是您编写查询的方式会非常慢。

SELECT f.*, ef.field_value
   FROM #__directory_field AS f
   LEFT JOIN #__directory_enf AS ef ON (f.id = ef.field_id AND ef.entry_id = $this->_id)
   WHERE f.published = 1
   ORDER BY f.ordering ASC

您的 ON 子句是主要问题。 以这种方式编写,您是 ant 跟踪每条记录,并且没有很好地利用索引。 您将需要颠倒您的表顺序,并将 id 匹配放在 where 子句中。 像这样的东西。

SELECT ef.field_value, f.*
   FROM #__directory_enf AS ef
   LEFT JOIN #__directory_field AS f ON f.id = ef.field_id
   WHERE f.published = 1 AND ef.entry_id = $this->_id
   ORDER BY f.ordering ASC

然后,您需要确保您的数据库在 f.id 和 ef.entry_id 字段上都有索引。 这应该使您的查询速度快很多倍。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM