Magento – How to get attribute value from order item by SQL

grid

how can I get the value of a custom attribute from an order item by SQL?
I don't want to use the collection.

Here is my try:

$this->getSelect()->reset()
    ->from(
        array('order_items' => $this->getTable('sales/order_item')),
        array(
            'ordered_qty' => 'SUM(order_items.qty_ordered)',
            'order_items_name' => 'order_items.name',
            'price' => 'order_items.price',
            'cost' => 'order_items.base_cost',
            'vendor' => 'attrval.value',
            'total_price' => '(order_items.qty_ordered * order_items.price)',
            'total_profit' => '(order_items.qty_ordered * order_items.price) - (order_items.qty_ordered * order_items.base_cost)',
            'sku' => 'order_items.sku'
        ))
    ->joinLeft(array('p' => 'catalog_product_entity'), 'order_items.product_id = p.entity_id')
    ->joinLeft(array('eav' => 'eav_attribute'), 'p.entity_type_id = eav.entity_type_id')
    ->joinLeft(array('attr' =>'eav_attribute_option'), 'attr.attribute_id = eav.attribute_id')
    ->joinLeft(array('attrval' =>'eav_attribute_option_value'), 'attrval.option_id = attr.option_id')
    ->where("eav.attribute_code='vendor'")
    ->where("order_items.created_at BETWEEN '".$from."' AND '".$to."'")
    ->where('parent_item_id IS NULL')
    ->group('order_items.product_id')
    ->having('SUM(order_items.qty_ordered) > ?', 0)
    ->order(
        array(
            'SUM(order_items.qty_ordered) DESC'
        ));

In SQL it is:

SELECT SUM(order_items.qty_ordered) AS `ordered_qty`, `order_items`.`name` AS `order_items_name`, `order_items`.`price`, `order_items`.`base_cost` AS `cost`, `attrval`.`value` AS `vendor`, (order_items.qty_ordered * order_items.price) AS `total_price`, (order_items.qty_ordered * order_items.price) - (order_items.qty_ordered * order_items.base_cost) AS `total_profit`, `order_items`.`sku`, `p`.*, `eav`.*, `attr`.*, `attrval`.* FROM `sales_flat_order_item` AS `order_items` LEFT JOIN `catalog_product_entity` AS `p` ON order_items.product_id = p.entity_id LEFT JOIN `eav_attribute` AS `eav` ON p.entity_type_id = eav.entity_type_id LEFT JOIN `eav_attribute_option` AS `attr` ON attr.attribute_id = eav.attribute_id LEFT JOIN `eav_attribute_option_value` AS `attrval` ON attrval.option_id = attr.option_id WHERE (eav.attribute_code='vendor') AND (order_items.created_at BETWEEN '2014-04-30 22:00:00' AND '2014-05-31 21:59:59') AND (parent_item_id IS NULL) GROUP BY `order_items`.`product_id` HAVING (SUM(order_items.qty_ordered) > 0) ORDER BY SUM(order_items.qty_ordered) DESCSELECT SUM(order_items.qty_ordered) AS `ordered_qty`, `order_items`.`name` AS `order_items_name`, `order_items`.`price`, `order_items`.`base_cost` AS `cost`, `attrval`.`value` AS `vendor`, (order_items.qty_ordered * order_items.price) AS `total_price`, (order_items.qty_ordered * order_items.price) - (order_items.qty_ordered * order_items.base_cost) AS `total_profit`, `order_items`.`sku`, `p`.*, `eav`.*, `attr`.*, `attrval`.* FROM `sales_flat_order_item` AS `order_items` LEFT JOIN `catalog_product_entity` AS `p` ON order_items.product_id = p.entity_id LEFT JOIN `eav_attribute` AS `eav` ON p.entity_type_id = eav.entity_type_id LEFT JOIN `eav_attribute_option` AS `attr` ON attr.attribute_id = eav.attribute_id LEFT JOIN `eav_attribute_option_value` AS `attrval` ON attrval.option_id = attr.option_id WHERE (eav.attribute_code='vendor') AND (order_items.created_at BETWEEN '2014-04-30 22:00:00' AND '2014-05-31 21:59:59') AND (parent_item_id IS NULL) GROUP BY `order_items`.`product_id` HAVING (SUM(order_items.qty_ordered) > 0) ORDER BY SUM(order_items.qty_ordered) DESC

With this code I get always the same value for my attribute 'vendor'.
Furthermore the order_qty sum is wrong. If I delete the following lines the sum is correct:

'vendor' => 'attrval.value',
->joinLeft(array('p' => 'catalog_product_entity'), 'order_items.product_id = p.entity_id')
    ->joinLeft(array('eav' => 'eav_attribute'), 'p.entity_type_id = eav.entity_type_id')
    ->joinLeft(array('attr' =>'eav_attribute_option'), 'attr.attribute_id = eav.attribute_id')
    ->joinLeft(array('attrval' =>'eav_attribute_option_value'), 'attrval.option_id = attr.option_id')
    ->where("eav.attribute_code='vendor'")

EDIT:

I changed the code on the top to this:

$this->_reset()
        ->addAttributeToSelect('*')
        ->addOrderedQty($from, $to)
        ->setOrder('ordered_qty', self::SORT_ORDER_DESC);

Now I get the correct values.
But how can I calculate the other columns (e.g. 'total_profit' => '(order_items.qty_ordered * order_items.price) – (order_items.qty_ordered * order_items.base_cost)')?

Best Answer

I have solved it by changing the addOrderedQty() function:

public function addOrderedQty($from = '', $to = '')
{
    $adapter              = $this->getConnection();
    $compositeTypeIds     = Mage::getSingleton('catalog/product_type')->getCompositeTypes();
    $orderTableAliasName  = $adapter->quoteIdentifier('order');

    $orderJoinCondition   = array(
        $orderTableAliasName . '.entity_id = order_items.order_id',
        $adapter->quoteInto("{$orderTableAliasName}.state <> ?", Mage_Sales_Model_Order::STATE_CANCELED),

    );

    $productJoinCondition = array(
        $adapter->quoteInto('(e.type_id NOT IN (?))', $compositeTypeIds),
        'e.entity_id = order_items.product_id',
        $adapter->quoteInto('e.entity_type_id = ?', $this->getProductEntityTypeId())
    );

    if ($from != '' && $to != '') {
        $fieldName            = $orderTableAliasName . '.created_at';
        $orderJoinCondition[] = $this->_prepareBetweenSql($fieldName, $from, $to);
    }

    $this->getSelect()->reset()
        ->from(
            array('order_items' => $this->getTable('sales/order_item')),
            array(
                'ordered_qty' => 'SUM(order_items.qty_ordered)',
                'order_items_name' => 'order_items.name',
                'total_price' => '(order_items.qty_ordered * order_items.price)',
                'total_profit' => '(order_items.qty_ordered * order_items.price) - (order_items.qty_ordered * order_items.base_cost)'
            ))
        ->joinInner(
            array('order' => $this->getTable('sales/order')),
            implode(' AND ', $orderJoinCondition),
            array())
        ->joinLeft(
            array('e' => $this->getProductEntityTableName()),
            implode(' AND ', $productJoinCondition),
            array(
                'entity_id' => 'order_items.product_id',
                'entity_type_id' => 'e.entity_type_id',
                'attribute_set_id' => 'e.attribute_set_id',
                'type_id' => 'e.type_id',
                'sku' => 'e.sku',
                'has_options' => 'e.has_options',
                'required_options' => 'e.required_options',
                'created_at' => 'e.created_at',
                'updated_at' => 'e.updated_at'
            ))
        ->where('parent_item_id IS NULL')
        ->group('order_items.product_id')
        ->having('SUM(order_items.qty_ordered) > ?', 0);
    return $this;
}