Problema relativo all'uso di "Avere" nella raccolta Magento


20

Sto cercando di creare una raccolta personalizzata per una griglia nel modulo di amministrazione Magento. Ho creato un nuovo metodo di raccolta chiamato "addAttributeHaving" che esegue solo le seguenti operazioni:

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

Vedi codice raccolta:

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

Questo produce il seguente SQL che viene eseguito perfettamente e produce i risultati previsti quando eseguito al di fuori di 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)

Tuttavia, quando provo a caricare la griglia all'interno di Magento ottengo il seguente errore:

SQLSTATE [42S22]: Colonna non trovata: 1054 Colonna sconosciuta "DIF_AU" in "clausola"

Inoltre, se rimuovo la clausola having (che interrompe i miei risultati), sono in grado di utilizzare la colonna DIF_AU per un'origine dati nella griglia.


1
AGGIORNAMENTO: Sono stato in grado di rintracciare il problema al metodo getSelectCountSql () padre. Questo è in realtà il problema che si verifica quando si tenta di ottenere il conteggio delle raccolte.
Anthony Leach Jr

1
Invia una risposta! Da dove sd_order_typeviene?
benmark

1
Elementi del tipo di ordine personalizzato top secret che sono stati aggiunti ai tavoli piatti. Sto ancora elaborando la risposta.
Anthony Leach Jr

1
"Gli utenti con meno di 10 reputazione non possono rispondere alla propria domanda per 8 ore dopo la domanda. Puoi rispondere in 7 ore. Fino ad allora, utilizza i commenti o modifica la tua domanda." (soluzione a venire tra 7 ore).
Anthony Leach Jr

1
Qualcuno dà a quest'uomo un
voto positivo

Risposte:


12

Risponderò effettivamente alla mia domanda qui. Lo so, pacchiano, ma mi sono imbattuto nella risposta guardando molto più da vicino la traccia dello stack reale. La raccolta si sta caricando correttamente, tuttavia l'errore si verifica un po 'più tardi nell'esecuzione quando proviamo a ottenere il conteggio delle raccolte in Varien_Data_Collection_Db :: getSelectCountSql () . L'SQL che viene prodotto da questo è:

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)

Noterai che l'istruzione HAVING è allegata, ma non abbiamo più alcuna definizione per la colonna DIF_AU. Sembra che dovrò estendere un getSelectCountSql personalizzato () nella mia classe di raccolta per ottenere il giusto conteggio dei record.

Ho creato un getSelectCountSql esteso () nella classe di raccolta personalizzata che si aggiunge nella colonna mancante richiesta per l'istruzione having.


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
Per niente pacchiano ... se capisci prima la soluzione, è incoraggiata. Altri lo troveranno potenzialmente utile lungo la strada. +1 :)
davidalger

Dovresti presentare una segnalazione di bug! magentocommerce.com/bug-tracking
benmarks

Questo è un problema che ho anche visto e ben fatto nel trovare una risposta. Tuttavia, non credo che la tua soluzione sia corretta - poiché stai utilizzando group by, SelectCountSql deve restituire il numero di gruppi. Quindi hai bisogno di un conteggio (fetchAll ()) o di riscrivere la tua query usando count(distinct main_table.entity_id)invece dicount(*)
Benubird

Penso che tu abbia molto probabilmente ragione. Questo progetto è stato in secondo piano da questo post, e proprio ora ci sto tornando. In una demo della scorsa settimana, ho notato un conteggio dei record errato segnalato nella griglia. Riporterò le mie scoperte una volta che le avrò risolte.
Anthony Leach Jr

@AnthonyLeachJr hai notizie sui tuoi risultati?
Simon,

0

Innanzitutto $countSelect->reset(Zend_Db_Select::HAVING);significa che verrà ripristinato HAVINGdalla tua raccolta. Ciò significa che rimuoverà la clausola having. E non è quello che vuoi. Puoi aggiungerlo alla raccolta ( app/code/core/Mage/Catalog/Model/Resource/Product/Collection.php->_getSelectCountSql()qui.)

Ma il principale colpevole è il getSize()metodo che esiste nel lib/Varien/Data/Collection/Db.phpfile.

Ho provato la soluzione sopra menzionata da @Anthony ma non ha funzionato.

Ora ho fatto il seguito.

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

Verifica che non stia nemmeno usando il getSelectCountSql(). Sto solo leggendo l'intero SQL QUERY e recuperando tutti i dati e restituendone il conteggio . È tutto.


0

Ho risolto questo problema qui: app / code / core / Mage / Catalog / Model / Resource / Product / Collection.php: 943 aggiungi questo: $ select-> reset (Zend_Db_Select :: HAVING);

Basta copiare app / codice / core / Mage / Catalog / Model / Resource / Product / Collection.php in app / code / local / Mage / Catalog / Model / Resource / Product / Collection.php

Il mio codice ora appare così:

/**
 * 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

Questa soluzione funzionerà se la tua selezione ha nomi di colonne univoci perché tutte le colonne nell'elenco di selezione delle sottoquery devono avere nomi univoci

Sottoquery: la sottoquery della tabella consente nomi di colonne duplicati

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: questa risposta è per le raccolte generali di magento. non correlato alla sola raccolta di prodotti.


0

Questo sta funzionando

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.