안티 조인 (Magento 1.9)을 사용 하여이 작업을 수행하는 더 나은 방법을 찾았습니다.
이 접근법의 장점
원래 답변에 비해이 방법의 장점은 오 탐지를 얻지 못하고 결과적으로 오류가 발생하기 쉽고 빠르다는 것입니다. 예를 들어 단일 제품이 있다고 가정합니다.
- 셔츠 (카테고리 : 1 | 2)
당신은 싶어 "하지의 모든 제품을 찾을 category 3
다음, 그들에게 추가 category 3
" . 따라서 NOT IN
쿼리 를 실행하면 두 개의 행이 반환됩니다 (name | category_id)
.
1. "Shirt" | 1
2. "Shirt" | 2
큰 문제는 없지만 Magento는 여전히 첫 번째 결과 만 반환 한 다음 추가합니다. 빼고 ! 이 쿼리가 두 번째로 실행될 때 동일한 결과가 나타납니다.
1. "Shirt" | 1
2. "Shirt" | 2
그리고 마 젠토는이 셔츠를 아직 추가하지 않았다고 알려줄 것입니다 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`;
설명:
제품과 제품 범주 관계 테이블이 주어진 경우 :
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 |
+-------------+-------------+
그런 다음 쿼리는 "ok, 이제 category_id가 NULL 인 모든 것을 제공합니다" 라고 말합니다 .