ฉันพบวิธีที่ดีกว่าในการทำเช่นนี้โดยใช้การต่อต้านการเข้าร่วม (Magento 1.9)
ประโยชน์ของวิธีนี้
ประโยชน์ของคำตอบนี้คือคุณจะไม่ได้รับผลบวกปลอมและมันจะเร็วขึ้นและเกิดข้อผิดพลาดน้อยลง ตัวอย่างเช่นสมมติว่าคุณมีผลิตภัณฑ์เดียว:
- เสื้อเชิ้ต (ในหมวดหมู่: 1 | 2)
คุณต้องการที่จะ"ได้พบกับผลิตภัณฑ์ทั้งหมดไม่ได้อยู่ในcategory 3
นั้นเพิ่มให้พวกเขาcategory 3
" ดังนั้นคุณเรียกใช้NOT IN
แบบสอบถามและมันจะกลับมาสองแถว(name | category_id)
:
1. "Shirt" | 1
2. "Shirt" | 2
ไม่มีเรื่องใหญ่เลยวีโอไอพีจะยังคงส่งคืนผลลัพธ์แรกเท่านั้นจากนั้นคุณเพิ่ม ยกเว้น ! ครั้งที่สองที่เรียกใช้แบบสอบถามนี้คุณมีผลลัพธ์เหมือนกัน:
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 |
+-------------+-------------+
จากนั้นแบบสอบถามแล้วกล่าวว่า"โอเคตอนนี้ให้ฉันทุกอย่างที่ category_id เป็นโมฆะ"