Problem mit "having" in der Magento-Sammlung

20

Ich versuche, eine benutzerdefinierte Sammlung für ein Raster im Magento Admin-Modul zu erstellen. Ich habe eine neue Erfassungsmethode mit dem Namen "addAttributeHaving" erstellt, die nur Folgendes ausführt:

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

Siehe Sammlungscode:

$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);

Dies erzeugt das folgende SQL, das einwandfrei ausgeführt wird und die erwarteten Ergebnisse liefert, wenn es außerhalb von Magento ausgeführt wird.

[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)

Wenn ich jedoch versuche, das Raster in Magento zu laden, wird folgende Fehlermeldung angezeigt:

SQLSTATE [42S22]: Spalte nicht gefunden: 1054 Unbekannte Spalte 'DIF_AU' in 'having clause'

Wenn ich außerdem die having-Klausel entferne (die meine Ergebnisse beeinträchtigt), kann ich die DIF_AU-Spalte für eine Datenquelle im Grid verwenden.

Anthony Leach Jr
quelle
1
UPDATE: Ich konnte das Problem auf die übergeordnete Methode getSelectCountSql () zurückführen. Dies ist tatsächlich der Punkt, an dem das Problem auftritt, wenn versucht wird, die Anzahl der Auflistungen zu ermitteln.
Anthony Leach Jr
1
Schreibe eine Antwort! WTH kommt das sd_order_typeher?
Benmarks
1
Streng geheime Sonderanfertigungen, die zu flachen Tischen hinzugefügt wurden. Ich arbeite immer noch an der Antwort.
Anthony Leach Jr
1
"Nutzer mit weniger als 10 Ruf können ihre Frage 8 Stunden lang nicht beantworten. Sie können sie in 7 Stunden beantworten. Bis dahin verwenden Sie bitte Kommentare oder bearbeiten Sie stattdessen Ihre Frage." (Lösung in 7 Stunden).
Anthony Leach Jr
1
Jemand gibt diesem Mann eine Gegenstimme
markiert den

Antworten:

12

Ich werde hier meine eigene Frage beantworten. Ich weiß, klebrig, aber ich bin auf die Antwort gestoßen, als ich mir die eigentliche Stapelspur genauer angesehen habe. Die Auflistung wird problemlos geladen , der Fehler tritt jedoch etwas später bei der Ausführung auf, wenn wir versuchen, die Anzahl der Auflistungen in Varien_Data_Collection_Db :: getSelectCountSql () abzurufen . Die SQL, die daraus erzeugt wird, ist:

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)

Sie werden feststellen, dass die HAVING-Anweisung angehängt ist, wir jedoch keine Definition für die DIF_AU-Spalte mehr haben. Es sieht so aus, als müsste ich ein benutzerdefiniertes getSelectCountSql () in meiner Auflistungsklasse erweitern, um die richtige Datensatzanzahl zu erhalten.

Ich habe ein erweitertes getSelectCountSql () in der benutzerdefinierten Auflistungsklasse erstellt, das in der fehlenden Spalte, die für die having-Anweisung erforderlich ist, wieder hinzugefügt wird.


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;
  }
Anthony Leach Jr
quelle
1
Überhaupt nicht klebrig ... wenn Sie zuerst die Lösung herausfinden, ist es ermutigt. Andere werden es möglicherweise später hilfreich finden. +1 :)
Davidalger
Sie sollten einen Fehlerbericht einreichen! magentocommerce.com/bug-tracking
benmarks
Dies ist ein Problem, das ich auch gesehen habe und das ich gut gemacht habe, um eine Antwort zu finden. Ich glaube jedoch nicht, dass Ihre Lösung korrekt ist - da Sie group by verwenden, muss SelectCountSql die Anzahl der Gruppen zurückgeben. So können Sie entweder eine Zählung (fetchAll ()) benötigen, gehen Sie bitte zu umschreiben mit count(distinct main_table.entity_id)stattcount(*)
Benubird
Ich denke, dass Sie sehr wahrscheinlich richtig sind. Dieses Projekt ist seit diesem Posting auf dem Rückgrat und kommt erst jetzt darauf zurück. In einer Demo in der letzten Woche habe ich festgestellt, dass im Raster eine falsche Anzahl von Datensätzen angezeigt wurde. Werde über meine Ergebnisse berichten, sobald ich sie gelöst habe.
Anthony Leach Jr
@AnthonyLeachJr Neuigkeiten zu Ihren Ergebnissen?
Simon
0

Zunächst $countSelect->reset(Zend_Db_Select::HAVING);bedeutet dies, dass es HAVINGaus Ihrer Sammlung zurückgesetzt wird. Das heißt, es wird die having-Klausel entfernen. Und es ist nicht das, was du willst. Möglicherweise möchten Sie es der Sammlung hinzufügen ( app/code/core/Mage/Catalog/Model/Resource/Product/Collection.php->_getSelectCountSql()hier.)

Aber der Hauptschuldige ist die getSize()Methode, die in der lib/Varien/Data/Collection/Db.phpDatei existiert .

Ich habe die oben genannte Lösung von @Anthony ausprobiert, aber das hat nicht funktioniert.

Jetzt habe ich das Folgende getan.

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);
}

Überprüfen Sie, dass ich nicht einmal das verwende getSelectCountSql(). Ich lese gerade die gesamte SQL - Abfrage und alle Daten zu holen und geben die Zählung davon. Das ist alles.

Kingshuk Deb
quelle
0

Ich habe dieses Problem hier behoben: app / code / core / Mage / Catalog / Model / Resource / Product / Collection.php: 943 füge dies hinzu: $ select-> reset (Zend_Db_Select :: HAVING);

Kopieren Sie einfach app / code / core / Mage / Catalog / Model / Resource / Product / Collection.php nach app / code / local / Mage / Catalog / Model / Resource / Product / Collection.php

Mein Code sieht jetzt so aus:

/**
 * 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);
Andrii K
quelle
0

Diese Lösung funktioniert, wenn Ihre Auswahl eindeutige Spaltennamen hat, da alle Spalten in der Unterabfrage-Auswahlliste eindeutige Namen haben müssen

Unterabfrage: Tabellenunterabfrage erlaubt doppelte Spaltennamen

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: Diese Antwort gilt für allgemeine Magento-Sammlungen. bezieht sich nicht nur auf die Produktkollektion.

Minesh Patel
quelle
0

Das funktioniert

öffentliche Funktion 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); }

Jignesh Patel
quelle