MySql query to get Woo variable products with other product info on same line - mysql

Trying to get the ID, name and SKU of products for each variable product that have a custom meta field with another product ID in WooCommerce in the same result row via only one MySql query.
This is the query I made:
SELECT wp_posts.id, wp_posts.post_title, wp_postmeta.meta_value AS dms3sku FROM wp_posts, wp_postmeta WHERE wp_posts.post_type = "product_variation" AND wp_posts.id = wp_postmeta.post_id AND wp_postmeta.meta_key = "dms3sku"
sql result
This returns me the ID, name, and a custom meta field of the variable product called dms3sku that is the ID of another product. So have to find the ID, name and SKU of the product with the ID I got on the previous query called dms3sku and I need it in the same query I did.
need a result like that
Haven't found anything on internet and my Sql knowladge is not enough to solve that.

Related

wordpress phpadmin SQL database query to get results in columns

In my wordpress website I have multiple custom fields under post type 'home_decor', using the below query returns two field 'post id' and 'hd_product_description'. Currently, I am using this query to export fields one by one and then vlookup by post id. I have 7 fields in total, can someone help me with the SQL query that will return all seven columns from wp_postmeta. I have to export data from time to time and its become a long process.
SELECT * FROM `wp_postmeta` WHERE `meta_key` = 'product_description'
post id product_description retail_price sale_price product_sku product_name
------- ------------------- ------------ ---------- ----------- ------------
1245 about the product $125 $115 1245alt furniture
Your problem is to retrieve multiple attributes for your posts from your wp_postmeta table. It's known as an entity - attribute - value table in the language of database design. It's a notorious pain in the xxx neck to use, but it is extensible.
You need to join the postmeta table multiple times for this, one time for each named attribute you want. Here is the pattern.
SELECT wp_posts.ID post_id,
product_description.meta_value product_description,
retail_price.meta_value retail_price
sale_price.meta_value sale_price
/* always start with wp_posts, because some attibutes might be missing */
FROM wp_posts
/* left join wp_postmeta giving it an alias. put meta_key into ON clause */
LEFT JOIN wp_postmeta product_description
ON product_description.post_id = wp_posts.ID
AND product_description.meta_key = 'product_description'
/* and again for the next attribute */
LEFT JOIN wp_postmeta retail_price
ON retail_price.post_id = wp_posts.ID
AND retail_price.meta_key = 'retail_price'
/* and again */
LEFT JOIN wp_postmeta sale_price
ON sale_price.post_id = wp_posts.ID
AND sale_price.meta_key = 'sale_price'
The trick is to use a separate LEFT JOIN to the wp_postmeta table for every attribute. For each of those LEFT JOIN operations, give the table an alias that's unique. For example LEFT JOIN wp_postmeta sale_price assigns the alias sale_price to this particular use of wp_postmeta.
Then, for each column in your SELECT clause, mention the alias and meta_value, then assign an alias to the column. For example, sale_price.meta_value sale_price.
Why LEFT JOIN instead of ordinary inner JOIN? If you used inner JOIN, your result set would only contain rows for posts that have every attribute you want. With LEFT JOIN you'll get NULL values for missing attributes. That is much more useful unless your data is absolutely perfect. (Umm, not much real world data is so perfect.)

Run MySQL SELECT query for each value, returned by another SELECT

Even though this is basically a WordPress related problem, my question is strictly MySQL, so I am posting here as it probably will be more accurate.
I have two tables, wp_posts that contains basic data (e.g. IDs) of my products, and wp_postmeta that contains all additional data of those posts. I have this query:
SELECT count(p.ID) as in_stock_count
FROM wp_postmeta as pm
INNER JOIN wp_posts as p
ON pm.post_id = p.ID
WHERE p.post_type = 'product_variation'
AND p.post_parent = 123456
AND p.post_status = 'publish'
AND pm.meta_key = '_stock_status'
AND pm.meta_value = 'instock'
I can pass my product ID to this query (note the 123456 ID) and it returns the number of available variations of that product (in_stock_count). The query works very well for a single product ID.
This is a simple query that returns all product IDs from the wp_posts table:
SELECT ID FROM wp_posts WHERE post_type = 'product' AND post_status = 'publish'
I need to somehow merge these two queries, so that the first query would run for each ID returned by the second query. The returned table could have two columns: ID and in_stock_count
I'm kind of stuck here. Thank you for your help.

Update several posts' attachment with SQL

I've tried in several different ways to write an SQL query that would insert/update post's image attachment, but I haven't succeeded. I'd like to change several posts' image to be the same.
In other words I'd like to update postmeta to value XXX where post's title contains certain string. The problem is that posts' titles are in posts table and not in the postmeta table so I would have to somehow get the title from posts using post's id.
This is what I've tried:
SELECT ID FROM wp_posts WHERE post_title LIKE ‘%*part of title*%’;
UPDATE wp_postmeta
SET meta_value = *attatchment-post’s id*
WHERE post_id IN (*post* *id’s which attachment is to be updated*) AND meta_key = ‘*my attachment field*’;
The second part works if I manually list all of the posts' id's. Basically id like to use the result of the SELECT query in the second UPDATE query.
Any ideas, thanks?
Doing it in the same line as you have written -
UPDATE wp_postmeta
SET meta_value = (select meta_value from wp_postmeta where post_id = *attatchment-post’s id* AND meta_key = '*my attachment*')
WHERE post_id IN (SELECT ID FROM wp_posts WHERE post_title LIKE ‘%*part of title*%’;
) AND meta_key = '*my attachment*'
In MySQL you can use joins in the update statements as well, and lift the where criteria from the select statement over to combine it with the update's where criteria:
update wp_postmeta wpm
inner join wp_posts wp on wpm.post_id=wp.id
set wpm.meta_value=*attatchment-post’s id*
where wpm.meta_key = ‘*my attachment field*’ and wp.post_title LIKE ‘%*part of title*%’

Get Multiple rows in SQL Query

I'm using a SQL query in JDBC. It is supposed to get:
1- post_id (from table wp_posts) WHERE post_type = product
2- post_title (from table wp_posts) WHERE post_type = product
3- meta_value from table wp_postmeta WHERE (wp_posts.post_id = wp_postmeta.post_id) AND wp_postmeta.meta_key = _stock_status, total_sales, _regular_price, _sale_price, _price, _stock
(from specified META_KEYs from table WP_POSTMETA corresponding to my POST_IDs from table WP_POSTS)
Basically, I'm working on getting WooCommerce product details from WP Database.
This is the code my friend has helped me with so far:
SELECT wp_posts.ID, wp_posts.post_title,wp_postmeta.meta_value FROM wp_posts, wp_postmeta WHERE (wp_posts.ID = wp_postmeta.post_id) AND (wp_postmeta.meta_key='_stock')
Just like it is getting _stock at the end of the query, I want to get 5 more items (_stock_status, total_sales, _regular_price, _sale_price, _price) for each POST_ID
EDIT:
My friend helped me with another query, but it is not getting the information in a single array, instead it makes different array items for each piece of information.
SELECT wp_posts.ID, wp_posts.post_title,wp_postmeta.meta_key,wp_postmeta.meta_value FROM wp_posts, wp_postmeta WHERE wp_posts.ID = wp_postmeta.post_id HAVING wp_postmeta.meta_key='_stock' OR wp_postmeta.meta_key='_stock_status' OR wp_postmeta.meta_key='total_sales' OR wp_postmeta.meta_key='_regular_price' OR wp_postmeta.meta_key='_sale_price' OR wp_postmeta.meta_key='_price'
I want the results to come out in a single 2D array.
This select statement below follows the question that wants to include additional meta_key information (not just "_stock"). Change accordingly, as only you have your data.
The OP clearly has typos in this sentence "wp_postmeta.meta_key = _stock_status, total_sales, _reulgar_price, _sale_price, _price, _stock" as well as that query that his "friend" wrote.
SELECT p.ID, p.post_title,m.meta_value
FROM wp_posts p
join wp_postmeta m
on p.ID=m.post_id
AND m.meta_key in ('_stock','_stock_status','total_sales','_regular_price','_sale_price','_price')

Woocommerce SQL query to show products sold this week?

Woocommerce has a reporting tool that will show me the top products sold for the last 7 days. But it only shows the top 12 products.
I am wanting to create a SQL query that will show me all products with their total count sold for the last 7 days instead of just the top 12.
Has anyone done this before?
WooCommerce borrows heavily from the way WordPress itself stores data: a Post serves as the basic data object with a handful of columns common to all custom posts. Any unique data specific to a custom type is stored as key value pairs in post_meta. This means there aren't clean columns or tables to query for things like order line items, sku, line item price, etc.
It's worth mentioning that for orders, WC does not store products it stores line items. This is because you can add fees, generic line items and possibly other things to an order that are not products. Also, WC needs to store the price at the time of the order as the customer may have had a discount or the product price may have changed.
WooCommerce uses both the WordPress postmeta table AND its own order_itemmeta table. Here's how that breaks down:
The order itself is stored as a custom post type of "shop_order" in the wp_posts table
Order line items are stored in a relationship table called wp_woocommerce_order_items
Order item details are stored as key value pairs in wp_woocommerce_order_itemmeta
Finaly order details are stored in the wp_postmeta table
So, let's say you want to see all line items for a period of time and you want to know things like the item title, price and what order it belonged to. To do this you must JOIN multiple tables and either JOIN or subquery the meta tables for the specific fields you want. In the example below I used subqueries because I believe they are more readable, please note that JOINs are very likely faster.
SELECT
-- Choose a few specific columns related to the order
o.ID as order_id,
o.post_date as order_created,
-- These come from table that relates line items to orders
oi.order_item_name as product_name,
oi.order_item_type as item_type,
-- We have to subquery for specific values and alias them. This could also be done as a join
(SELECT meta_value FROM wp_woocommerce_order_itemmeta WHERE order_item_id = oi.order_item_id AND meta_key = "_product_id") as product_id,
(SELECT meta_value FROM wp_woocommerce_order_itemmeta WHERE order_item_id = oi.order_item_id AND meta_key = "_product_variation_id") as variant_id,
(SELECT meta_value FROM wp_woocommerce_order_itemmeta WHERE order_item_id = oi.order_item_id AND meta_key = "_qty") as qty,
(SELECT meta_value FROM wp_woocommerce_order_itemmeta WHERE order_item_id = oi.order_item_id AND meta_key = "_fee_amount") as fee,
(SELECT meta_value FROM wp_woocommerce_order_itemmeta WHERE order_item_id = oi.order_item_id AND meta_key = "_line_subtotal") as subtotal,
(SELECT meta_value FROM wp_woocommerce_order_itemmeta WHERE order_item_id = oi.order_item_id AND meta_key = "_line_subtotal_tax") as tax,
(SELECT meta_value FROM wp_woocommerce_order_itemmeta WHERE order_item_id = oi.order_item_id AND meta_key = "_line_total") as total,
(SELECT meta_value FROM wp_woocommerce_order_itemmeta WHERE order_item_id = oi.order_item_id AND meta_key = "_tax_class") as tax_class,
(SELECT meta_value FROM wp_woocommerce_order_itemmeta WHERE order_item_id = oi.order_item_id AND meta_key = "_tax_status") as tax_status,
-- This wasn't specifically mentioned in the question but it might be nice to have some order meta data too
(SELECT meta_value FROM wp_postmeta WHERE post_id = o.ID AND meta_key = "_order_total") as order_total,
(SELECT meta_value FROM wp_postmeta WHERE post_id = o.ID AND meta_key = "_customer_user") as user_id
FROM wp_posts o
LEFT JOIN wp_woocommerce_order_items oi ON oi.order_id = o.id
LEFT JOIN wp_posts p ON p.ID = oi.order_item_id
WHERE o.post_type = "shop_order"
As you can see it takes a subquery/join for every line item field you want making these queries pretty expensive. I suspect that WC limits how much is queried for reports for this reason.
This answer was tested against WC version 3.3.4.
Instead of writin a new query just modify the existing one with filter:
woocommerce_reports_get_order_report_query
Is seems that the limit is the same for all parts of the reports page, so changing this will affect all queries with limit clause. I would not go too far with the number of products because a new sql query is executed for each product listed.
add_filter( 'woocommerce_reports_get_order_report_query', function( $query )
{
if ( isset( $query['limit'] ) ) $query['limit'] = 'LIMIT 20'; <-- set limit to 20 products
return $query;
});
Just a guess
....WHERE dateColumn BETWEEN DATE_SUB(NOW(),INTERVAL 1 WEEK) AND NOW()
Add more info,for a more precise answer.