Masalah menggunakan "memiliki" dalam koleksi Magento

20

Saya mencoba membangun koleksi khusus untuk kisi-kisi di modul admin Magento. Saya telah membuat metode pengumpulan baru yang disebut "addAttributeHaving" yang hanya melakukan hal berikut:

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

Lihat kode koleksi:

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

Ini menghasilkan SQL berikut yang dieksekusi dengan sangat baik dan menghasilkan hasil yang diharapkan ketika dijalankan di luar 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)

Namun, ketika saya mencoba memuat kotak di dalam Magento saya mendapatkan kesalahan berikut:

SQLSTATE [42S22]: Kolom tidak ditemukan: 1054 Kolom tidak dikenal 'DIF_AU' di 'memiliki klausa'

Selain itu, jika saya menghapus klausa memiliki (yang merusak hasil saya), saya dapat menggunakan kolom DIF_AU untuk sumber data di Grid.

Anthony Leach Jr
sumber
1
UPDATE: Saya bisa melacak masalah ke metode getSelectCountSql () induk. Di sinilah masalahnya terjadi ketika mencoba untuk mendapatkan jumlah koleksi.
Anthony Leach Jr
1
Posting jawaban! Dari mana itu sd_order_typeberasal?
patokan
1
Jenis jenis pesanan khusus rahasia yang telah ditambahkan ke tabel datar. Saya masih mencari jawabannya.
Anthony Leach Jr
1
"Pengguna dengan reputasi kurang dari 10 tidak dapat menjawab pertanyaan mereka sendiri selama 8 jam setelah bertanya. Anda dapat menjawab dalam 7 jam. Sampai saat itu silakan gunakan komentar, atau edit pertanyaan Anda sebagai gantinya." (solusi untuk datang dalam 7 jam).
Anthony Leach Jr
1
Seseorang memberikan suara
positif

Jawaban:

12

Saya benar-benar akan menjawab pertanyaan saya sendiri di sini. Saya tahu, norak, tetapi saya menemukan jawabannya ketika melihat lebih dekat pada jejak tumpukan yang sebenarnya. Koleksi ini memuat baik-baik saja, namun kegagalannya muncul sedikit lebih lambat ketika kami mencoba mendapatkan jumlah koleksi di Varien_Data_Collection_Db :: getSelectCountSql () . SQL yang dihasilkan dari ini adalah:

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)

Anda akan melihat bahwa pernyataan HAVING terlampir namun kami tidak memiliki definisi untuk kolom DIF_AU lagi. Tampaknya saya perlu memperpanjang getSelectCountSql () kustom di kelas koleksi saya untuk mendapatkan jumlah catatan yang tepat.

Saya telah membuat getSelectCountSql () yang diperluas di kelas koleksi khusus yang menambahkan kembali di kolom yang hilang yang diperlukan untuk pernyataan memiliki.


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
sumber
1
Sama sekali tidak norak ... jika Anda mencari solusinya terlebih dahulu, itu dianjurkan. Orang lain akan berpotensi merasa terbantu di jalan. +1 :)
davidalger
Anda harus mengajukan laporan bug! magentocommerce.com/bug-tracking
patok
Ini adalah masalah yang juga saya lihat, dan berhasil menemukan jawaban. Namun, saya tidak berpikir solusi Anda benar - karena Anda menggunakan grup oleh, SelectCountSql Anda harus mengembalikan jumlah grup. Jadi, Anda memerlukan hitungan (fetchAll ()), atau untuk menulis ulang kueri menggunakan count(distinct main_table.entity_id)bukancount(*)
Benubird
Saya pikir Anda sangat mungkin benar. Proyek ini telah berada di back burner sejak posting ini, dan baru saja kembali ke sana. Dalam sebuah demo minggu lalu, saya melihat jumlah catatan yang salah dilaporkan di grid. Akan melaporkan kembali temuan saya setelah saya menyelesaikannya.
Anthony Leach Jr
@AnthonyLeachJr ada berita tentang temuan Anda?
Simon
0

Pertama-tama $countSelect->reset(Zend_Db_Select::HAVING);berarti itu akan diatur ulang HAVINGdari koleksi Anda. Itu berarti akan menghapus klausa yang memiliki. Dan bukan itu yang Anda inginkan. Anda mungkin ingin menambahkannya ke koleksi (di app/code/core/Mage/Catalog/Model/Resource/Product/Collection.php->_getSelectCountSql()sini.)

Namun penyebab utamanya adalah getSize()metode yang ada dalam lib/Varien/Data/Collection/Db.phpfile.

Saya mencoba solusi di atas yang disebutkan oleh @Anthony tapi itu tidak berhasil.

Sekarang saya lakukan di bawah ini.

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

Periksa saya bahkan tidak menggunakan getSelectCountSql(). Saya hanya membaca seluruh QUERY SQL dan mengambil semua data dan mengembalikannya . Itu saja.

Kingshuk Deb
sumber
0

Saya memperbaiki masalah ini di sini: app / code / core / Mage / Katalog / Model / Sumber Daya / Produk / Collection.php: 943 tambahkan ini: $ select-> reset (Zend_Db_Select :: HAVING);

Cukup salin aplikasi / kode / inti / Penyihir / Katalog / Model / Sumber Daya / Produk / Collection.php ke aplikasi / kode / lokal / Penyihir / Katalog / Model / Sumber Daya / Produk / Collection.php

Kode saya terlihat seperti ini:

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

Solusi ini akan berfungsi jika pilih Anda memiliki nama kolom unik karena setiap kolom dalam daftar pilih subquery harus memiliki nama unik

Subquery: subquery tabel memungkinkan nama kolom duplikat

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: Jawaban ini untuk koleksi magento umum. tidak terkait dengan hanya koleksi produk.

Minesh Patel
sumber
0

Ini bekerja

fungsi publik getSize () {if (is_null ($ this -> _ totalRecords)) {// $ sql = $ this-> getSelectCountSql (); $ sql = $ this-> getSelect (); $ this -> _ totalRecords = count ($ this-> getConnection () -> fetchAll ($ sql, $ this -> _ bindParams)); } mengembalikan intval ($ this -> _ totalRecords); }

jignesh patel
sumber