Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Woocommerce mySQL Query - List All Orders, Users and Purchased Items

I have a fully working mySQL query which pulls all of the orders, users, addresses and items purchased from Woocommerce, however it only lists the products individually, and I would like to add the quantity for each product displayed.

Currently shows 'Items Ordered'
Running Shoes
Walking Shoes

Where it should show 'Items Ordered'
3 x Running Shoes
4 x Walking Shoes

SELECT
  p.ID AS 'Order ID',
  p.post_date AS 'Purchase Date',
  MAX( CASE WHEN pm.meta_key = '_billing_email'       AND p.ID = pm.post_id THEN pm.meta_value END ) AS 'Email Address',
  MAX( CASE WHEN pm.meta_key = '_billing_first_name'  AND p.ID = pm.post_id THEN pm.meta_value END ) AS 'First Name',
  MAX( CASE WHEN pm.meta_key = '_billing_last_name'   AND p.ID = pm.post_id THEN pm.meta_value END ) AS 'Last Name',
  MAX( CASE WHEN pm.meta_key = '_billing_address_1'   AND p.ID = pm.post_id THEN pm.meta_value END ) AS 'Address',
  MAX( CASE WHEN pm.meta_key = '_billing_city'        AND p.ID = pm.post_id THEN pm.meta_value END ) AS 'City',
  MAX( CASE WHEN pm.meta_key = '_billing_state'       AND p.ID = pm.post_id THEN pm.meta_value END ) AS 'State',
  MAX( CASE WHEN pm.meta_key = '_billing_postcode'    AND p.ID = pm.post_id THEN pm.meta_value END ) AS 'Post Code',
    CASE p.post_status
      WHEN 'wc-pending'    THEN 'Pending Payment'
      WHEN 'wc-processing' THEN 'Processing'
      WHEN 'wc-on-hold'    THEN 'On Hold'
      WHEN 'wc-completed'  THEN 'Completed'
      WHEN 'wc-cancelled'  THEN 'Cancelled'
      WHEN 'wc-refunded'   THEN 'Refunded'
      WHEN 'wc-failed'     THEN 'Failed'
    ELSE 'Unknown'
    END AS 'Purchase Status',
  MAX( CASE WHEN pm.meta_key = '_order_total'         AND p.ID = pm.post_id THEN pm.meta_value END ) AS 'Order Total',
  MAX( CASE WHEN pm.meta_key = '_paid_date'           AND p.ID = pm.post_id THEN pm.meta_value END ) AS 'Paid Date',
  ( select group_concat( order_item_name separator '</p>' ) FROM wp_woocommerce_order_items where order_id = p.ID ) AS 'Items Ordered'
FROM  wp_posts AS p
JOIN  wp_postmeta AS pm ON p.ID = pm.post_id
JOIN  wp_woocommerce_order_items AS oi ON p.ID = oi.order_id
WHERE post_type = 'shop_order'
GROUP BY p.ID

I believe Woocommerce stores the QTY in the following table / entries:

wp_woocommerce_order_itemmeta
  order_item_id
    SELECT wp_woocommerce_order_itemmeta.meta_value
    WHERE wp_woocommerce_order_itemmeta.meta_value = '_qty' and wp_woocommerce_order_itemmeta.order_item_id =

And I need to join it in somehow into this section:

( select group_concat( order_item_name separator '</p>' ) FROM wp_woocommerce_order_items where order_id = p.ID ) AS 'Items Ordered'

Thanks in advance.

UPDATED WITH ANSWER FROM: Lucek

Thanks Lucek, absolutely perfect.

I've combined the complete query in case anyone else wants to copy it.

SELECT
  p.ID AS 'Order ID',
  p.post_date AS 'Purchase Date',
  MAX( CASE WHEN pm.meta_key = '_billing_email'       AND p.ID = pm.post_id THEN pm.meta_value END ) AS 'Email Address',
  MAX( CASE WHEN pm.meta_key = '_billing_first_name'  AND p.ID = pm.post_id THEN pm.meta_value END ) AS 'First Name',
  MAX( CASE WHEN pm.meta_key = '_billing_last_name'   AND p.ID = pm.post_id THEN pm.meta_value END ) AS 'Last Name',
  MAX( CASE WHEN pm.meta_key = '_billing_address_1'   AND p.ID = pm.post_id THEN pm.meta_value END ) AS 'Address',
  MAX( CASE WHEN pm.meta_key = '_billing_city'        AND p.ID = pm.post_id THEN pm.meta_value END ) AS 'City',
  MAX( CASE WHEN pm.meta_key = '_billing_state'       AND p.ID = pm.post_id THEN pm.meta_value END ) AS 'State',
  MAX( CASE WHEN pm.meta_key = '_billing_postcode'    AND p.ID = pm.post_id THEN pm.meta_value END ) AS 'Post Code',
    CASE p.post_status
      WHEN 'wc-pending'    THEN 'Pending Payment'
      WHEN 'wc-processing' THEN 'Processing'
      WHEN 'wc-on-hold'    THEN 'On Hold'
      WHEN 'wc-completed'  THEN 'Completed'
      WHEN 'wc-cancelled'  THEN 'Cancelled'
      WHEN 'wc-refunded'   THEN 'Refunded'
      WHEN 'wc-failed'     THEN 'Failed'
    ELSE 'Unknown'
    END AS 'Purchase Status',
  MAX( CASE WHEN pm.meta_key = '_order_total'         AND p.ID = pm.post_id THEN pm.meta_value END ) AS 'Order Total',
  MAX( CASE WHEN pm.meta_key = '_paid_date'           AND p.ID = pm.post_id THEN pm.meta_value END ) AS 'Paid Date',
  ( SELECT GROUP_CONCAT(CONCAT(m.meta_value, ' x ', i.order_item_name) separator '</br>' )
    FROM wp_woocommerce_order_items i
    JOIN wp_woocommerce_order_itemmeta m ON i.order_item_id = m.order_item_id AND meta_key = '_qty'
    WHERE i.order_id = p.ID AND i.order_item_type = 'line_item') AS 'Items Ordered',
  MAX( CASE WHEN pm.meta_key = 'post_excerpt'         AND p.ID = pm.post_id THEN pm.meta_value END ) AS 'User Comments'
FROM  wp_posts AS p
JOIN  wp_postmeta AS pm ON p.ID = pm.post_id
JOIN  wp_woocommerce_order_items AS oi ON p.ID = oi.order_id
WHERE post_type = 'shop_order'
GROUP BY p.ID
like image 526
Miles Avatar asked Oct 30 '18 05:10

Miles


People also ask

How do I check my WooCommerce database orders?

If you search the post_type field for 'shop_order', SQL will retrieve all orders. Just like the WooCommerce products, the orders are also just a custom post type, which means they can be found under the wp_posts table. One way of finding them is to search the database for shop_order under the column post_type.

How are WooCommerce orders stored in database?

Woocommerce Orders are stored in the database as custom posts. The custom post type is named shop_order. The WordPress post ID maps to the order ID and the post status describes the status of the order (ex: wc-pending).


1 Answers

You need to replace Items Ordered section with this:

( SELECT GROUP_CONCAT(CONCAT(m.meta_value, ' x ', i.order_item_name) separator '</p>' )
FROM da_woocommerce_order_items i
JOIN da_woocommerce_order_itemmeta m ON i.order_item_id = m.order_item_id AND meta_key = '_qty'
WHERE i.order_id = p.ID AND i.order_item_type = 'line_item') AS 'Items Ordered'

You can change separator between product name and quantity in CONCAT function, now it is ' x '. I also add i.order_item_type = 'line_item' to where clause - it prevents from getting shipping, fees and coupons. If you need it all in your query - just delete it.

like image 189
Lucek Avatar answered Sep 18 '22 20:09

Lucek