简体   繁体   中英

Codeigniter - Join same table and search with array

I have two input fields. Both leading to an array array of colors that will be matched on the database. The arrays can look like this

Array ( [0] => red [1] => blue [2] => green ) 

One input is used for searching a table called ´image_topcolor´ and the other input is searching another table, ´image_bottomcolor´.
I'm trying to come up with a structure to search for images with these two inputs based on color selection.

I want the user to be able to select several colors and then return all images which has the selected color in the database. The search works fine when using only one input field with the following code:

$this->db->select('*'); 
$this->db->from('image');

if(!empty($top_colors[0]) && empty($bottom_colors[0])) {
$this->db->join('image_topcolor', 'image_topcolor.image_id = image.id' ,'inner');
$this->db->join('color', 'color.id = image_topcolor.color_id', 'inner');
}
if(!empty($bottom_colors[0]) && empty($top_colors[0])) {    
$this->db->join('image_bottomcolor', 'image_bottomcolor.image_id = image.id' ,'inner'); 
$this->db->join('color', 'color.id = image_bottomcolor.color_id', 'inner');
}

if(!empty($bottom_colors[0])) {     
$this->db->where_in('color', $bottom_colors); 
}
if(!empty($top_colors[0])) {
$this->db->where_in('color', $top_colors); 
}

This returns images to the user even if the user has selected a color that doesn't have an id matched with an image yet, which is perfect!

I want this to work the same way when using both input fields to find all images that matches the colors from the inputs.

I want to use something similiar to:

$this->db->select('*'); 
$this->db->from('image');

if(!empty($top_colors[0]) && !empty($bottom_colors[0])) {
$this->db->join('image_topcolor', 'image_topcolor.image_id = image.id' ,'left');
$this->db->join('image_bottomcolor', 'image_bottomcolor.image_id = image.id' ,'left');      
$this->db->join('color as a', 'image_topcolor.color_id = a.id','left');
$this->db->join('color as b', 'image_bottomcolor.color_id = b.id','left');
}

if(!empty($top_colors[0]) && !empty($bottom_colors[0])) {
$this->db->where_in('a', $top_colors); 
$this->db->where_in('b', $bottom_colors); 
}

This returns with the error

"Column 'color' in where clause is ambiguous"

"SELECT * FROM image LEFT JOIN image_topcolor ON image_topcolor . image_id = image . id LEFT JOIN image_bottomcolor ON image_bottomcolor . image_id = image . id LEFT JOIN color as a ON image_topcolor . color_id = a . id LEFT JOIN color as b ON image_bottomcolor . color_id = b . id WHERE color IN('blue') AND color IN('red') AND a . color IN('red') AND b . color IN('blue')"

I'm not sure how I can use both arrays to find all images that matches any of the selected colors.
My tables looks like this:

image

id | color | info
---|-------|------
1  | blue  | foo
2  | red   | bar

color

id | color |
---|-------|
1  | red   |
2  | blue  | 
3  | green |

image_topcolor

image_id | color_id |
---------|----------|
1        | 1        |
1        | 2        |

image_bottomcolor

image_id | color_id |
---------|----------|
2        | 1        |
2        | 3        |

Sorry for the long post. Question recap: How can I get the results of all images with matching colors when using both inputs? Just like I get when using only one input.
Thanks!

Update
This query is now not generating any errors.
But I'm still not getting the results if the user selects a color that doesn't exist. I only get the result if the image has the same selected color in both tables. Example: An image has red, blue top_color and blue, green bottom color. I cannot get this result by searching for red top and green bottom. However if I search for blue top and blue bottom, I get the result. I guess this has do with the joins?

$this->db->select('*'); 
    $this->db->from('image');
    if(!empty($top_colors[0]) && !empty($bottom_colors[0])) {
    $this->db->join('image_topcolor', 'image_topcolor.image_id = image.id' ,'left');
    $this->db->join('image_bottomcolor', 'image_bottomcolor.image_id = image.id' ,'left');  


$this->db->join('color as a', 'image_topcolor.color_id = a.id','left');
$this->db->join('color as b', 'image_bottomcolor.color_id = b.id','left');

if(!empty($top_colors[0]) && !empty($bottom_colors[0])) {
$result = array_merge($top_colors, $bottom_colors);

$this->db->where_in('a.color', $top_colors); 
$this->db->where_in('b.color', $bottom_colors);

}

Since you joined the same table twice, the two tables have exactly the same set of fields. Therefore, every time you reference a field from one of these two tables, you need to prefix the field name with the table alias, such as a.color .

I believe in codeigniter you can achieve this in the following way:

...
$this->db->where_in('a.color', $top_colors); 
$this->db->where_in('b.color', $bottom_colors);
...

You did not use the where_in syntax correct. You need to use the name of the field as the first argument of the function, not the table name (alias).

Try this:

if(!empty($top_colors[0]) && !empty($bottom_colors[0])) {
$this->db->where_in('a.color', $top_colors); 
$this->db->where_in('b.color', $bottom_colors); 
}

UPDATE: To get your desired result you should also use or_where_in, like this:

if(!empty($top_colors[0]) && !empty($bottom_colors[0])) {
  $this->db->where_in('a.color', $top_colors);
  $this->db->or_where_in('b.color', $bottom_colors); 
}

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