简体   繁体   English

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

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

The problem I am having is that using the current function below is taking much too long to load.我遇到的问题是使用下面的当前 function 加载时间太长。 The two tables that are being joined consist of thousands of rows apiece.正在连接的两个表各包含数千行。 The specific function that holds the table join is the &getFields() function in the model section below.保存表连接的特定 function 是下面 model 部分中的&getFields() function。

I was thinking that I could possibly have a function that initially checked whether the request was to edit or add new and then deal with separating the table join on only edit queries (No clue as to how to accomplish this).我在想我可能有一个 function 最初检查请求是编辑还是添加新的,然后处理仅在编辑查询上分离表连接(不知道如何完成此操作)。


Call From Page Initial Page - using an html form with post method从页面初始页面调用- 使用 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 Directing Traffic To Model 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 That Holds The Actual Functions拥有实际功能的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 is the fastest method, but you have written your query in such a way that it will be very slow. 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

Your ON clause is the main problem.您的 ON 子句是主要问题。 Written this way you are ant trailing through every record, and not putting good use to indexes.以这种方式编写,您是 ant 跟踪每条记录,并且没有很好地利用索引。 You will want to reverse your table order, and put the id match in the where clause.您将需要颠倒您的表顺序,并将 id 匹配放在 where 子句中。 Something like this.像这样的东西。

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

You will then want to make sure your database has indexes on both the f.id and ef.entry_id fields.然后,您需要确保您的数据库在 f.id 和 ef.entry_id 字段上都有索引。 This should make your query many many times faster.这应该使您的查询速度快很多倍。

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

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