Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>You're using a lot of objects wrappers in your sample script. Methods like <code>load</code> encapsulated into multiple loops will produce huge delays and possibly huge memory usage (base on your product collection size).</p> <p>When I addressed this issue the other day I decided to use straight ORM methods instead of objects for better performance.</p> <p>There are two possible ways to show bestsellers. The less resources-consuming is to use aggregated bestsellers tables (like <code>sales_bestsellers_aggregated_daily</code>), but it has huge drawback - the data inside those tables is not updating authomatically. It's used in Admin Reports section, and will be updates only when you choose to refresh your statistics.</p> <p>The other but much more reliable method is to join <code>sales_flat_order_item</code> table to retrieve sales_qty for each product. Obviously it's more resource consuming, since you have to count it yourself.</p> <p>In my script I've chosen the latter path. I've modified it to meet your logic requirements. Also I've added a couple of <code>joins</code> to get Category name, you might not need that. But enough talking :) here's the code of my <code>test.php</code> shell script:</p> <pre><code>&lt;?php require_once 'abstract.php'; /** * Magento Test Bestsellers script * * @category Mage * @package Mage_Shell */ class Mage_Shell_Test extends Mage_Shell_Abstract { /** * Run script * */ public function run() { // benchmarking $memory = memory_get_usage(); $time = microtime(); echo "Starting mem usage: $memory\n"; $catId = $this-&gt;getArg('category'); /** @var $collection Mage_Catalog_Model_Resource_Product_Collection */ $collection = Mage::getResourceModel('catalog/product_collection'); // join sales order items column and count sold products $expression = new Zend_Db_Expr("SUM(oi.qty_ordered)"); $condition = new Zend_Db_Expr("e.entity_id = oi.product_id AND oi.parent_item_id IS NULL"); $collection-&gt;addAttributeToSelect('name')-&gt;getSelect() -&gt;join(array('oi' =&gt; $collection-&gt;getTable('sales/order_item')), $condition, array('sales_count' =&gt; $expression)) -&gt;group('e.entity_id') -&gt;order('sales_count' . ' ' . 'desc'); // join category $condition = new Zend_Db_Expr("e.entity_id = ccp.product_id"); $condition2 = new Zend_Db_Expr("c.entity_id = ccp.category_id"); $collection-&gt;getSelect()-&gt;join(array('ccp' =&gt; $collection-&gt;getTable('catalog/category_product')), $condition, array())-&gt;join(array('c' =&gt; $collection-&gt;getTable('catalog/category')), $condition2, array('cat_id' =&gt; 'c.entity_id')); $condition = new Zend_Db_Expr("c.entity_id = cv.entity_id AND ea.attribute_id = cv.attribute_id"); // cutting corners here by hardcoding 3 as Category Entiry_type_id $condition2 = new Zend_Db_Expr("ea.entity_type_id = 3 AND ea.attribute_code = 'name'"); $collection-&gt;getSelect()-&gt;join(array('ea' =&gt; $collection-&gt;getTable('eav/attribute')), $condition2, array())-&gt;join(array('cv' =&gt; $collection-&gt;getTable('catalog/category') . '_varchar'), $condition, array('cat_name' =&gt; 'cv.value')); // if Category filter is on if ($catId) { $collection-&gt;getSelect()-&gt;where('c.entity_id = ?', $catId)-&gt;limit(1); } // unfortunately I cound not come up with the sql query that could grab only 1 bestseller for each category // so all sorting work lays on php $result = array(); foreach ($collection as $product) { /** @var $product Mage_Catalog_Model_Product */ if (isset($result[$product-&gt;getCatId()])) { continue; } $result[$product-&gt;getCatId()] = 'Category:' . $product-&gt;getCatName() . '; Product:' . $product-&gt;getName() . '; Sold Times:'. $product-&gt;getSalesCount(); } print_r($result); // benchmarking $memory2 = memory_get_usage(); $time2 = microtime(); $memDiff = ($memory2 - $memory)/1000000; $timeDiff = $time2 - $time; echo 'Time spent:' . $timeDiff . "s\n"; echo "Ending mem usage: $memory2\n"; echo "Mem used : {$memDiff}M\n"; } /** * Retrieve Usage Help Message * */ public function usageHelp() { return &lt;&lt;&lt;USAGE Usage: php -f test.php -- [options] php -f test.php -- --category 1 --categories &lt;category&gt; Filter by Category, if not specified, all categories are outputted help This help USAGE; } } $shell = new Mage_Shell_Test(); $shell-&gt;run(); </code></pre> <p>To use it just create a file <code>test.php</code> in your <em>shell</em> folder and insert the code I've provided into the file. See <code>usageHelp</code> if you're not familiar with command line php calls.</p> <p>P.S. Added some benchmarking there to track your mem_usage and time.</p> <p><strong>UPDATE</strong> Upon reviewing the issue further I've found more elegant way to get the Bestsellers for each category using only <code>Zend_Db</code> adapter. The result will contain only <code>category_id</code> => <code>product_id</code> connection (not Magento Objects), but it's much easier and overall better. This code should go between the <em>benchmarking</em> blocks into the <code>run</code> function:</p> <pre><code> $catId = $this-&gt;getArg('category'); /** @var $resource Mage_Core_Model_Resource */ $resource = Mage::getModel('core/resource'); /** @var $adapter Zend_Db_Adapter_Abstract */ $adapter = $resource-&gt;getConnection('core_read'); $select = $adapter-&gt;select() -&gt;from(array('c' =&gt; $resource-&gt;getTableName('catalog/category')), array('cat_id'=&gt;'entity_id')) -&gt;join(array('ccp' =&gt; $resource-&gt;getTableName('catalog/category_product')), 'c.entity_id = ccp.category_id', array()) -&gt;join(array('oi' =&gt; $resource-&gt;getTableName('sales/order_item')), 'ccp.product_id = oi.product_id', array('max_qty' =&gt; new Zend_Db_Expr('SUM(oi.qty_ordered - oi.qty_canceled)'), 'product_id' =&gt; 'product_id')) -&gt;where('oi.parent_item_id is null') -&gt;group('c.entity_id') -&gt;group('oi.product_id') -&gt;order('entity_id ASC') -&gt;order('max_qty DESC'); if ($catId) { $select-&gt;where('c.entity_id = ?', $catId); } $res = $adapter-&gt;fetchAll($select); $result = array(); foreach ($res as $oneRes) { if (isset($result[$oneRes['cat_id']])) { continue; } $result[$oneRes['cat_id']] = $oneRes; } array_walk($result, function($var, $key) { echo 'Category Id:' . $key . ' | Product Id:' . $var['product_id'] . ' | Sales Count:' . $var['max_qty'] . "\n"; }); </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload