简体   繁体   English

限制 SQL 加入时使用 CodeIgniter 活动记录 class

[英]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?无论如何使用CI活动记录class将db->join限制为1条记录?

Add $this->db->limit(1);添加$this->db->limit(1); before calling $this->db->get('products p');在调用$this->db->get('products p'); . . See the docs at ellislab.com : search the page for limit .请参阅ellislab.com上的文档:在页面中搜索limit

EDIT: I misread the fact that you were trying to apply the LIMIT to the internal JOIN statement.编辑:我误读了您试图将 LIMIT 应用于内部 JOIN 语句的事实。

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.不,由于您不能在常规 SQL 中对内部 JOIN 语句执行 LIMIT,因此您不能使用 Code Igniter 的 ActiveRecord ZA2F2ED4F8EBC2CBB4C21A29DC40AB61Z 来执行此操作。

You can achieve what you want using $this->db->group_by with a left join:您可以使用带有left连接的$this->db->group_by来实现您想要的:

$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.这应该通过products.id为您提供结果(不重复产品),并将products_images中的第一个匹配记录连接到每个结果行。 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.如果连接表中没有匹配的行(即如果缺少图像),您将获得 products_images 字段的 null 值,但仍会从products表中看到结果。

To expand on @Femi's answer:扩展@Femi的答案:

There's no good way to limit the JOIN , and, in fact, you don't really want to.没有限制JOIN的好方法,事实上,你也不想这样做。 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.假设products_image.product_idproducts.id都有索引(如果你要反复加入它们,它们绝对应该)当数据库引擎进行连接时,它使用索引来确定它需要获取哪些行。 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:通过运行这些 SQL 语句,您应该能够看到差异:

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.如果 product_id 存在于前一个中,那么我解决的方法也是迭代结果并删除当前的 object。 Create a array, push the product_id's to it while checking if they are repeats.创建一个数组,将 product_id 推送给它,同时检查它们是否重复。

$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现在 $result 就是我们想要的

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

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