アンチ結合(Magento 1.9)を使用して、これを行うより良い方法を見つけました。
このアプローチの利点
元の回答に対するこれの利点は、誤検知が発生しないことであり、その結果、より速く、エラーが発生しにくくなります。たとえば、次の1つの製品があるとします。
- シャツ(カテゴリー:1 | 2)
あなたはしたくない「で、すべての製品を見つけcategory 3
、その後、それらを追加しますcategory 3
」。NOT IN
クエリを実行すると、2つの行が返されます(name | category_id)
。
1. "Shirt" | 1
2. "Shirt" | 2
たいしたことではありません。Magentoは最初の結果のみを返し、それを追加します。を除いて!このクエリを2回目に実行すると、同じ結果になります。
1. "Shirt" | 1
2. "Shirt" | 2
そして、Magentoは、まだこのシャツをに追加していないことを教えてくれますcategory 3
。これは、商品が複数のカテゴリに属している場合、「catalog_product_entity」テーブルに複数の行があるためです。したがって、a LEFT JOIN
は複数の結果を返します。
これは望ましくない
- 結果セットは必要以上に大きくなり、必要以上のメモリを消費します。特に、何千ものアイテムの非常に大きな在庫がある場合はそうです。
- PHPで追加のチェックを実行して、結果が誤検知(例:)であるかどうかを確認する必要があり
in_array($categoryThree, $product->getCategories())
ます。つまり、不要な結果をループすることになります。これにより、特に大量のインベントリで、スクリプト/コードが遅くなります。
解決
// All products not in this category ID
$notInThisCatId = '123';
$filteredProducts = Mage::getModel('catalog/product')->getCollection();
$filteredProducts
->joinField('category_id', 'catalog_category_product', 'category_id', 'product_id=entity_id', ['category_id'=>$notInThisCatId], 'left');
$filteredProducts
->addAttributeToFilter('category_id', [
['null' => true]
]);
生成されるSQLクエリは次のようになります。
SELECT
DISTINCT `e`.*, `at_category_id`.`category_id`
FROM `catalog_product_entity` AS `e`
LEFT JOIN `catalog_category_product` AS `at_category_id`
ON (at_category_id.`product_id`=e.entity_id) AND (at_category_id.category_id = '123')
WHERE (at_category_id.category_id IS NULL)
GROUP BY `e`.`entity_id`;
説明:
productとproduct <=> categoryの関係テーブルを考えます:
catalog_product_entity
+-----------+
| ENTITY_ID |
+-----------+
| 423 |
| 424 |
| 425 |
+-----------+
catalog_category_product
+-------------+------------+
| CATEGORY_ID | PRODUCT_ID |
+-------------+------------+
| 3 | 423 |
| 123 | 424 |
| 3 | 425 |
+-------------+------------+
あなたのクエリが、言っている「に私のすべての行を与えるcatalog_product_entity 『』、とにペースト『CATEGORY_ID』から列catalog_category_product 『』。それからちょうどそのCATEGORY_ID = 124私の行を与えます」。
これは左結合なので、常に"catalog_product_entity"からの行が含まれます。照合できない行の場合、次のようになりますNULL
。
結果
+-------------+-------------+
| ENTITY_ID | CATEGORY_ID |
+-------------+-------------+
| 423 | NULL |
| 424 | 123 |
| 425 | NULL |
+-------------+-------------+
そこから、クエリは「わかりました。これで、category_idがNULLであるすべてのものを取得してください」と言います。