2013-02-23 70 views
2

如何使用收集過濾器來實現以下功能?如何在Magento的OR條件中添加AND過濾器/條件?

SELECT * FROM products WHERE (name like '%blah%' and name like 
    '%yes%') or (description like '%blah%' and description like '%yes%'); 

或者出於某種原因,這是不好的做法?

addFieldToFilter的應用到集合做,並在每一個可以實現OR,但這僅允許:

(x OR y) AND (w OR z) 

但不

(x AND y) OR (w AND z) 

我缺少的東西?

回答

4

不,我不相信你錯過了什麼。我碰到類似的問題,並且使用getSelect()->where()來解決它。

與您的查詢開始:

SELECT * FROM products WHERE (name like '%blah%' and name like 
'%yes%') or (description like '%blah%' and description like '%yes%'); 

首先,我創建了一個收集和使用的OR陣列方法來獲取查詢。

$collection = Mage::getModel('catalog/product')->getCollection(); 
$collection->addFieldToFilter(array(
           array('attribute' => 'name', 'like' => '%blah%'), 
           array('attribute' => 'name', 'like' => '%yes%') 
          )); 
$collection->addFieldToFilter(array(
           array('attribute' => 'description', 'like' => '%blah%'), 
           array('attribute' => 'description', 'like' => '%yes%') 
          )); 
$collection->load(true); // To dump the sql as text 

這導致了以下的輸出:

SELECT `e`.*, IF(at_name.value_id > 0, at_name.value, at_name_default.value) AS `name`, IF(at_description.value_id > 0, at_description.value, at_description_default.value) AS `description` FROM `catalog_product_entity` AS `e` INNER JOIN `catalog_product_entity_varchar` AS `at_name_default` ON (`at_name_default`.`entity_id` = `e`.`entity_id`) AND (`at_name_default`.`attribute_id` = '96') AND `at_name_default`.`store_id` = 0 LEFT JOIN `catalog_product_entity_varchar` AS `at_name` ON (`at_name`.`entity_id` = `e`.`entity_id`) AND (`at_name`.`attribute_id` = '96') AND (`at_name`.`store_id` = 1) INNER JOIN `catalog_product_entity_text` AS `at_description_default` ON (`at_description_default`.`entity_id` = `e`.`entity_id`) AND (`at_description_default`.`attribute_id` = '97') AND `at_description_default`.`store_id` = 0 LEFT JOIN `catalog_product_entity_text` AS `at_description` ON (`at_description`.`entity_id` = `e`.`entity_id`) AND (`at_description`.`attribute_id` = '97') AND (`at_description`.`store_id` = 1) 
WHERE ((IF(at_name.value_id > 0, at_name.value, at_name_default.value) LIKE '%blah%') OR (IF(at_name.value_id > 0, at_name.value, at_name_default.value) LIKE '%yes%')) AND ((IF(at_description.value_id > 0, at_description.value, at_description_default.value) LIKE '%blah%') OR (IF(at_description.value_id > 0, at_description.value, at_description_default.value) LIKE '%yes%')) 

你會發現WHERE說法幾乎是在那裏你描述它除了ORAND是相反的。

我複製查詢的WHERE部分和增加了一個額外getSelect()->where()線到集合是這樣的:

$collection = Mage::getModel('catalog/product')->getCollection(); 

// I added these lines to ensure that the collection would load 
// the fields and do the necessary joins to pull the data 
$collection->addFieldToFilter('name');   
$collection->addFieldToFilter('description'); 

// I'm using the same WHERE statement but I have set the ANDs and ORs 
// to match your requirements 

$collection->getSelect()->where(" (IF(at_name.value_id > 0, at_name.value, at_name_default.value) LIKE '%blah%') AND (IF(at_name.value_id > 0, at_name.value, at_name_default.value) LIKE '%yes%')) OR ((IF(at_description.value_id > 0, at_description.value, at_description_default.value) LIKE '%blah%') AND (IF(at_description.value_id > 0, at_description.value, at_description_default.value) LIKE '%yes%')"); 

$collection->load(true); // To dump the sql as text again 

產生的輸出是:

SELECT `e`.*, IF(at_name.value_id > 0, at_name.value, at_name_default.value) AS `name`, IF(at_description.value_id > 0, at_description.value, at_description_default.value) AS `description` FROM `catalog_product_entity` AS `e` INNER JOIN `catalog_product_entity_varchar` AS `at_name_default` ON (`at_name_default`.`entity_id` = `e`.`entity_id`) AND (`at_name_default`.`attribute_id` = '96') AND `at_name_default`.`store_id` = 0 LEFT JOIN `catalog_product_entity_varchar` AS `at_name` ON (`at_name`.`entity_id` = `e`.`entity_id`) AND (`at_name`.`attribute_id` = '96') AND (`at_name`.`store_id` = 1) INNER JOIN `catalog_product_entity_text` AS `at_description_default` ON (`at_description_default`.`entity_id` = `e`.`entity_id`) AND (`at_description_default`.`attribute_id` = '97') AND `at_description_default`.`store_id` = 0 LEFT JOIN `catalog_product_entity_text` AS `at_description` ON (`at_description`.`entity_id` = `e`.`entity_id`) AND (`at_description`.`attribute_id` = '97') AND (`at_description`.`store_id` = 1) 
WHERE (IF(at_name.value_id > 0, at_name.value, at_name_default.value) = '') AND (IF(at_description.value_id > 0, at_description.value, at_description_default.value) = '') AND ((IF(at_name.value_id > 0, at_name.value, at_name_default.value) LIKE '%blah%') AND (IF(at_name.value_id > 0, at_name.value, at_name_default.value) LIKE '%yes%')) OR ((IF(at_description.value_id > 0, at_description.value, at_description_default.value) LIKE '%blah%') AND (IF(at_description.value_id > 0, at_description.value, at_description_default.value) LIKE '%yes%')) 

getSelect()where()可以是縮寫爲:

(`name` like '%blah%' and `name` like '%yes%') or (`description` like '%blah%' and `description` like '%yes%'); 

任何其他Magento人在那裏請隨時糾正我,如果我太遠離這個基地或如果你知道的方式來實現相同的目標,而不使用這種方法。

hth!

+0

感謝您的分享。我希望有一個Magento方法,爲了一致起見,我們可以避免編寫SQL,但這是一個功能性的解決方案。 – Tyler 2013-03-03 08:18:46