简体   繁体   中英

Limit SQL join when using CodeIgniter active record class

I'm getting a product listing. Each product may have 1 or more image, I only want to return the first image.

$this->db->select('p.product_id, p.product_name i.img_name, i.img_ext');    
$this->db->join('products_images i', 'i.product_id = p.product_id', 'left');
$query = $this->db->get('products p');

Is there anyway to limit the db->join to 1 record using the CI active record class?

Add $this->db->limit(1); before calling $this->db->get('products p'); . See the docs at ellislab.com : search the page for limit .

EDIT: I misread the fact that you were trying to apply the LIMIT to the internal JOIN statement.

No. Since you can not do a LIMIT on an internal JOIN statement in regular SQL you can not do it with Code Igniter's ActiveRecord class.

You can achieve what you want using $this->db->group_by with a left join:

$this->db->select('products.id, products.product_name, products_images.img_name, products_images.img_ext');
$this->db->from('products');
$this->db->join('products_images', 'products_images.product_id = products.id', 'left');
$this->db->group_by('products.id'); 
$query = $this->db->get();

This should give you results by products.id (without repetition of products), with the first matching record from products_images joined to each result row. If there's no matching row from the joined table (ie if an image is missing) you'll get null values for the products_images fields but will still see a result from the products table.

To expand on @Femi's answer:

There's no good way to limit the JOIN , and, in fact, you don't really want to. Assuming both products_image.product_id and products.id have indexes (and they absolutely should if you're going to join against them repeatedly) when the database engine does a join, it uses the indexes to determine what rows it needs to fetch. Then the engine uses the results to determine where on the disk to find the records it needs. If you

You should be able to see the difference by running these SQL statements:

EXPLAIN 
SELECT p.product_id, p.product_name, i.img_name, i.img_ext
FROM products p
LEFT JOIN products_images i
    ON i.product_id = p.product_id

as opposed to:

EXPLAIN  
SELECT p.product_id, p.product_name, i.img_name, i.img_ext
FROM (SELECT product_id, product_name FROM products) p 
LEFT JOIN (SELECT img_name, img_ext FROM products_images) i
    ON i.product_id = p.product_id

The first query should have an index, the second one will not. There should be a performance difference if there's a significant number of rows the the DB.

Had this issue too the way I solved it was iterating over the results and removing the current object if the product_id had existed in a previous one. Create a array, push the product_id's to it while checking if they are repeats.

$product_array = array();
$i = 0;

foreach($result as $r){

    if(in_array($r->product_id,$product_array)){
        unset($result[$i]);
    }else{
        array_push($product_array,$r->product_id);
    }
    $i++;

} 

$result = array_values($result); //re-index result array

Now $result is what we want

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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