2

コレクション フィルターを使用して次のことを実現するにはどうすればよいですか?

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

それとも、これは何らかの理由で悪い習慣ですか?

コレクションに適用された addFieldToFilter は AND を実行し、それぞれの中で OR を達成できますが、これは以下のみ可能です:

(x OR y) AND (w OR z) 

だがしかし

(x AND y) OR (w AND z)

何か不足していますか?

4

1 に答える 1

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%'))

where()は次のようgetSelect()に短縮できます。

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

他の Magento 関係者で、私がこれにあまりにも的外れである場合、またはこの方法を使用せずに同じ目標を達成する方法を知っている場合は、遠慮なく訂正してください。

ひ!

于 2013-02-23T20:12:55.480 に答える