In the previous articles (1, 2) you might find the way how to add custom column/attribute to adminhtml (orders, customers, ect) grid. But this is another example. In our article we will use the layout handles for inserting columns to the orders grid. First of all, you should create a new module (in our case Atwix_ExtendedGrid) and define layout update for adminhtml:
<!--file: app/code/local/Atwix/ExtendedGrid/etc/config.xml-->
<adminhtml>
    ...
    <layout>
        <updates>
            <atwix_extendedgrid>
                <file>atwix/extendedgrid.xml</file>
            </atwix_extendedgrid>
        </updates>
    </layout>
    ...
</adminhtml>
Note, this configuration is enough for adding fields from sales_flat_order_grid table (no sql joins are needed). But most likely, you will also need to add some field from the external table. For this purpose we use sales_order_grid_collection_load_before event to join extra tables. Here is how the observer configuration looks like:
<!--file: app/code/local/Atwix/ExtendedGrid/etc/config.xml-->
<adminhtml>
    ...
    <events>
        <sales_order_grid_collection_load_before>
            <observers>
                <atwix_extendedgrid>
                    <model>atwix_extendedgrid/observer</model>
                    <method>salesOrderGridCollectionLoadBefore</method>
                </atwix_extendedgrid>
            </observers>
        </sales_order_grid_collection_load_before>
    </events>
    ...
</adminhtml>
Then, add a function that handles our event to the observer:
/*file: app/code/local/Atwix/ExtendedGrid/Model/Observer.php*/
    /**
     * Joins extra tables for adding custom columns to Mage_Adminhtml_Block_Sales_Order_Grid
     * @param $observer
     */
    public function salesOrderGridCollectionLoadBefore($observer)
    {
        $collection = $observer->getOrderGridCollection();
        $select = $collection->getSelect();
        $select->joinLeft(array('payment'=>$collection->getTable('sales/order_payment')), 'payment.parent_id=main_table.entity_id',array('payment_method'=>'method'));
    }
As you can see, we join sales_flat_order_payment table to get a payment method field.Now, it is time to add this field to the grid. We will use layout handles to call addColumnAfter method of sales_order.grid (Mage_Adminhtml_Block_Sales_Order_Grid) block. There are two handles that we are interested in: adminhtml_sales_order_index and adminhtml_sales_order_grid. The same code goes to both sections, so we will define a new handle sales_order_grid_update_handle and use update directive. And finally, here is how our layout file looks like:
<!--file: app/design/adminhtml/default/default/layout/atwix/extendedgrid.xml -->
<layout>
    <sales_order_grid_update_handle>
        <reference name="sales_order.grid">
            <action method="addColumnAfter">
                <columnId>payment_method</columnId>
                <arguments>
                    <header>Payment Method</header>
                    <index>payment_method</index>
                    <filter_index>payment.method</filter_index>
                    <type>text</type>
                </arguments>
                <after>shipping_name</after>
            </action>
        </reference>
    </sales_order_grid_update_handle>
    <adminhtml_sales_order_grid>
        <!-- apply layout handle defined above -->
        <update handle="sales_order_grid_update_handle" />
    </adminhtml_sales_order_grid>
    <adminhtml_sales_order_index>
        <!-- apply layout handle defined above -->
        <update handle="sales_order_grid_update_handle" />
    </adminhtml_sales_order_index>
</layout>
After all steps you should see your column: Orders_Sales_Magento_Admin Here is a source code of the completed module. I hope you will find this article useful!

Update. For those who are interested in adding SKU column please check our new article. Thanks for reading us!