在Magento集合中使用“具有”问题


20

我正在尝试在Magento管理模块中为网格构建自定义集合。我创建了一个名为“ addAttributeHaving”的新收集方法,该方法仅执行以下操作:

public function addAttributeHaving($value)
{
    $this->getSelect()->having($value);
    return $this;
}

请参阅收集代码:

$collection->addFieldToSelect(
    array(
        'entity_id',
        'created_at',
        'increment_id',
        'customer_email',
        'customer_firstname',
        'customer_lastname',
        'grand_total',
        'status'
    )
);

$collection->getSelect()->joinLeft(array('sfop' => 'sales_flat_order_payment'), 'main_table.entity_id = sfop.parent_id', 'sfop.amount_authorized');
$collection->getSelect()->columns('sum(sfop.amount_authorized) AS AUTHD');
$collection->getSelect()->columns('grand_total - sum(sfop.amount_authorized) AS DIF_AU');
$collection->addFieldToFilter('main_table.state', array('in' => array('new','payment_review')));
$collection->addFieldToFilter('main_table.sd_order_type', array('neq' => 7));
$collection->addFieldToFilter('sfop.method', array('neq' => 'giftcard'));
$collection->addFieldToFilter('main_table.created_at', array('gt' => $this->getFilterDate()));
$collection->getSelect()->group(array('main_table.entity_id'));
$collection->addAttributeHaving('DIF_AU <> 0');
$collection->load(true,true);

$this->setCollection($collection);

这将产生以下SQL,该SQL执行得很好,并且在Magento之外运行时会产生预期的结果。

[METHOD=Varien_Data_Collection_Db->printLogQuery] SELECT `main_table`.`entity_id`, `main_table`.`entity_id`, `main_table`.`created_at`, `main_table`.`increment_id`, `main_table`.`customer_email`, `main_table`.`customer_firstname`, `main_table`.`customer_lastname`, `main_table`.`grand_total`, `main_table`.`status`, `sfop`.`amount_authorized`, sum(sfop.amount_authorized) AS `AUTHD`, grand_total - sum(sfop.amount_authorized) AS `DIF_AU` FROM `sales_flat_order` AS `main_table` LEFT JOIN `sales_flat_order_payment` AS `sfop` ON main_table.entity_id = sfop.parent_id WHERE (main_table.state in ('new', 'payment_review')) AND (main_table.sd_order_type != 7) AND (sfop.method != 'giftcard') AND (main_table.created_at > '2013-04-07') GROUP BY `main_table`.`entity_id` HAVING (DIF_AU <> 0)

但是,当我尝试在Magento中加载网格时,出现以下错误:

SQLSTATE [42S22]:找不到列:1054“具有子句”中的未知列“ DIF_AU”

此外,如果删除了hading子句(这会破坏我的结果),则可以将DIF_AU列用于Grid中的数据源。


1
更新:我能够找到问题的父getSelectCountSql()方法。实际上,这是试图获取集合计数时发生问题的地方。
Anthony Leach Jr'13年

1
发表答案!那是什么sd_order_type来的?
benmarks

1
已添加到平面表的最高机密的自定义订单类型的东西。我仍在寻找答案。
Anthony Leach Jr'13年

1
“声誉低于10的用户在询问后8个小时内无法回答自己的问题。您可以在7个小时内回答。在此之前,请使用注释或编辑您的问题。” (解决方案将在7小时内完成)。
Anthony Leach Jr'13年

1
有人给这个男人的给予好评
benmarks

Answers:


12

我将在这里实际回答我自己的问题。我知道,俗气,但是当我更仔细地查看实际堆栈跟踪时,我偶然发现了答案。集合可以很好地加载,但是,当我们尝试在Varien_Data_Collection_Db :: getSelectCountSql()中获取集合计数时,失败会在执行的稍后出现。由此产生的SQL是:

SELECT COUNT(*) FROM sales_flat_order AS main_table LEFT JOIN sales_flat_order_payment AS sfop ON main_table.entity_id = sfop.parent_id WHERE (main_table.state in ('payment_review')) AND (main_table.sd_order_type != 7) AND (sfop.method != 'giftcard') AND (main_table.created_at > '2013-04-07') GROUP BY main_table.entity_id HAVING (DIF_AU <> 0)

您会注意到HAVING语句已附加,但我们不再为DIF_AU列定义。似乎我将需要在我的收集类中扩展自定义getSelectCountSql()以获得正确的记录计数。

我在自定义集合类中创建了扩展的getSelectCountSql(),将其添加回Have语句所需的缺少列中。


public function getSelectCountSql()
  {
    $countSelect = parent::getSelectCountSql();
    $countSelect->columns('grand_total - sum(sfop.amount_authorized) AS DIF_AU');
    $countSelect->reset(Zend_Db_Select::GROUP);
    return $countSelect;
  }

1
一点也不俗气……如果您首先想出解决方案,那是值得鼓励的。其他人可能会发现它在将来很有帮助。+1 :)
davidalger

您应该提交错误报告!magentocommerce.com/bug-tracking
benmarks

我也看到了这个问题,并且在找到答案方面做得很好。但是,我认为您的解决方案不正确-因为您使用的是group by,因此SelectCountSql需要返回的组数。因此,您需要使用count(fetchAll())或使用count(distinct main_table.entity_id)而不是count(*)
-Benubird

我认为您很可能是正确的。自发布以来,该项目一直处于落后状态,而现在又回到了该项目。在上周的一个演示中,我注意到网格中报告的记录数不正确。解决后将报告我的发现。
Anthony Leach Jr

@AnthonyLeachJr您的发现有任何新闻吗?
西蒙(Simon)

0

首先$countSelect->reset(Zend_Db_Select::HAVING);意味着它将HAVING从您的收藏中重置。这意味着它将删除having子句。而且它不是您想要的。您可能需要将其添加到集合中(app/code/core/Mage/Catalog/Model/Resource/Product/Collection.php->_getSelectCountSql()此处)。

但主要的罪魁祸首getSize()lib/Varien/Data/Collection/Db.php文件中存在的方法。

我尝试了@Anthony提到的上述解决方案,但是没有用。

现在我做了以下。

public function getSize()
{
    if (is_null($this->_totalRecords)) {
        //$sql = $this->getSelectCountSql();
        $sql = $this->getSelect();
        $this->_totalRecords = count($this->getConnection()->fetchAll($sql, $this->_bindParams));
    }
    return intval($this->_totalRecords);
}

检查我什至没有使用getSelectCountSql()。我只是读取整个SQL查询,获取所有数据返回其计数。就这样。


0

我在这里解决了这个问题:app / code / core / Mage / Catalog / Model / Resource / Product / Collection.php:943添加此:$ select-> reset(Zend_Db_Select :: HAVING);

只需将app / code / core / Mage / Catalog / Model / Resource / Product / Collection.php复制到app / code / local / Mage / Catalog / Model / Resource / Product / Collection.php

我的代码现在看起来像这样:

/**
 * Build clear select
 *
 * @param Varien_Db_Select $select
 * @return Varien_Db_Select
 */
protected function _buildClearSelect($select = null)
{
    if (is_null($select)) {
        $select = clone $this->getSelect();
    }
    $select->reset(Zend_Db_Select::ORDER);
    $select->reset(Zend_Db_Select::LIMIT_COUNT);
    $select->reset(Zend_Db_Select::LIMIT_OFFSET);
    $select->reset(Zend_Db_Select::COLUMNS);
    $select->reset(Zend_Db_Select::HAVING);

0

如果您的选择具有唯一的列名称,则此解决方案将起作用,因为子查询选择列表中的任何列都必须具有唯一的名称。

子查询:表子查询允许重复的列名

public function getSelectCountSql()
{
    $this->_renderFilters();
    $select = clone $this->getSelect();
    $select->reset(Zend_Db_Select::ORDER);
    $select->reset(Zend_Db_Select::LIMIT_COUNT);
    $select->reset(Zend_Db_Select::LIMIT_OFFSET);        

    $countSelect = clone $this->getSelect();
    $countSelect->reset();
    $countSelect->from(array('a' => $select), 'COUNT(*)');
    return $countSelect;
}

PS:这个答案适用于一般的magento收藏。仅与产品收集无关。


0

这工作

公共功能getSize(){if(is_null($ this-> _ totalRecords)){// $ sql = $ this-> getSelectCountSql(); $ sql = $ this-> getSelect(); $ this-> _ totalRecords = count($ this-> getConnection()-> fetchAll($ sql,$ this-> _ bindParams)); } return intval($ this-> _ totalRecords); }

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.