Grab Multiple Rows MYSQL Join - mysql

This applies to WordPress / Woocommerce
I'm using this query to grab a specific meta_value based matching post_ids in wp_postmeta and wp_posts
SELECT meta.meta_value
FROM wp_postmeta AS meta
JOIN wp_posts AS o
ON meta.post_id = o.ID
WHERE o.post_type = 'shop_order' AND o.post_status='wc-cancelled' AND meta.meta_key='_billing_email'
ORDER BY o.post_date DESC
My problem is I also want to get meta.meta_keys = '_billing_first_name' and '_billing_last_name' for those same conditions in the same query. Right now I have to get each row separately then combine them on an excel sheet.
Is there a way to do this?

If I understand correctly, a simple OR or using IN will do
SELECT meta.meta_value
FROM wp_postmeta AS meta
JOIN wp_posts AS o
ON meta.post_id = o.ID
WHERE o.post_type = 'shop_order' AND o.post_status='wc-cancelled'
AND meta.meta_key IN ('_billing_email' , '_billing_first_name', '_billing_last_name')
ORDER BY o.post_date DESC

Related

How to delete entries from a SELECT query result in mysql?

I have the following SQL query :
SELECT wp_posts.* , wicl_translations.*
FROM wp_posts wp_posts join wp_icl_translations wicl_translations
ON (wicl_translations.element_id = wp_posts.ID)
WHERE (wicl_translations.language_code = 'es-es'
AND wicl_translations.element_type ='post_product'
AND wp_posts.post_type = 'product' ) GROUP BY wp_posts.ID
This returns all the results I need to delete from my database so I have tried several DELETE queries but getting syntax errors in all of them .
Example :
DELETE FROM wp_posts
WHERE (
SELECT wp_posts.* , wicl_translations.*
FROM wp_posts wp_posts join wp_icl_translations wicl_translations
ON (wicl_translations.element_id = wp_posts.ID)
WHERE (wicl_translations.language_code = 'pt-pt'
AND wicl_translations.element_type ='post_product'
AND wp_posts.post_type = 'product' ) GROUP BY wp_posts.ID
)
);
Also tried this :
DELETE FROM wp_posts WHERE wp_posts.ID = ANY IN (
SELECT wp_posts.ID, wicl_translations.*
FROM wp_posts wp_posts join wp_icl_translations wicl_translations
ON (wicl_translations.element_id = wp_posts.ID)
WHERE (wicl_translations.language_code = 'es-es'
AND wicl_translations.element_type ='post_product'
AND wp_posts.post_type = 'product' ) GROUP BY wp_posts.ID
)
It`s a complex aggregated query and I lack the mysql knowledge to properly write a rule for deleting these results .
How could I approach this ?
Thanks
If we have a complex query that returns the id value of rows in wp_posts that we want to delete (assuming that id is the primary key or a unique key of a row in the table)... as an example
SELECT p.id
FROM wp_posts p
JOIN wp_icl_translations t
ON t.element_id = p.id
WHERE t.language_code = 'es-es'
AND t.element_type = 'post_product'
AND p.post_type = 'product'
GROUP
BY p.id
We can then use that query as an inline view. We wrap the query in parens and reference it in the FROM clause of another query. MySQL requires that we assign an alias to thhe inline view (or derived table in the MySQL vernacular).
We can join the result from the inline view that back to the table we want to remove rows from. We write this a SELECT statement first
SELECT r.*
FROM ( -- inline view
SELECT p.id
FROM wp_posts p
JOIN wp_icl_translations t
ON t.element_id = p.id
WHERE t.language_code = 'es-es'
AND t.element_type = 'post_product'
AND p.post_type = 'product'
GROUP
BY p.id
) q
JOIN wp_posts r
ON r.id = q.id
to return the set of rows to be removed. We can verify that this is the intended set, or insert (create table as) the set of rows into backup...
Once we are confident that the SELECT is returning the rows we want to remove, we can convert it into a DELETE statement by replacing the SELECT keyword with DELETE.
DELETE r.*
FROM ( -- inline view
SELECT p.id
FROM wp_posts p
JOIN wp_icl_translations t
ON t.element_id = p.id
WHERE t.language_code = 'es-es'
AND t.element_type = 'post_product'
AND p.post_type = 'product'
GROUP
BY p.id
) q
JOIN wp_posts r
ON r.id = q.id
You'r on the right track !
You just miss the correct WHERE condition :
DELETE FROM wp_posts WHERE wp_posts.ids IN (...)
Make sure the result has only one column wich you shall refer to when deleting data from the targetted tables. The delete queries will be equal to the number of tables you will require to delete from ie.
DELETE FROM table_1 where common_column in (YOUR_SELECT_QUERY);
DELETE FROM table_2 where common_column in (YOUR_SELECT_QUERY);
DELETE FROM table_3 where common_column in (YOUR_SELECT_QUERY);
DELETE FROM table_nth where common_column in (YOUR_SELECT_QUERY);
Your select query be like,
SELECT GROUP_CONCAT(temp_tbl.ID) FROM (SELECT wp_posts.* , wicl_translations.*
FROM wp_posts wp_posts join wp_icl_translations wicl_translations
ON (wicl_translations.element_id = wp_posts.ID)
WHERE (wicl_translations.language_code = 'es-es'
AND wicl_translations.element_type ='post_product'
AND wp_posts.post_type = 'product' ) GROUP BY wp_posts.ID) AS temp_tbl

How to filter the GROUP_CONCAT in my SELECT

I am trying to SELECT (all of the multiple) comments from Wordpress which relate to a post (wp_comments.comment_content) with GROUP_CONCAT but I only want to select those comments which DON'T contain the text string "status". If there are no comments at all, or only comments which contain "status" I still want to see those records in the result, just without getting anything back for comments.
When I tried putting a condition similar to [WHERE wp_comments.comment_content NOT LIKE "%status%"] at the end of the complete query, records which only have a comment containing "status" don't display AT ALL, I still need to get those records, just without the comments.
I want to try something like the below version but this throws up an error and doesn't spit out any data at all. (The overall query works as expected btw apart from the comment selection section..).
Maybe I am joining the wp_comments table in the wrong place, using the wrong join, not using a properly formatted nested SELECT or similar, maybe it needs a separate SELECT at the end so I can get the comments back I want in a way which doesn't effect which records are selected overall.. not sure..
Any idea what I am doing wrong or how to approach this?
Here is my query, thanks in advance for any kind pointers!
select wp_woocommerce_order_itemmeta.meta_value as firstwoometavalue,
wp_postmeta.meta_value as firstwpmetavalue, Y.meta_value as ymetavalue,
Z.meta_value as zmetavalue, X.meta_value as xmetavalue,
(GROUP_CONCAT(wp_comments.comment_content) as commentcontent
WHERE wp_comments.comment_type = "order_note" AND
wp_comments.comment_content NOT LIKE "%status%")
FROM wp_postmeta
left JOIN wp_postmeta as Y
ON wp_postmeta.post_id = Y.post_id
left JOIN wp_posts
ON wp_postmeta.post_id = wp_posts.ID
left JOIN wp_woocommerce_order_items
ON wp_woocommerce_order_items.order_id = wp_posts.ID
left JOIN wp_woocommerce_order_itemmeta
ON wp_woocommerce_order_itemmeta.order_item_id = wp_woocommerce_order_items.order_item_id
left JOIN wp_woocommerce_order_itemmeta as Z
ON wp_woocommerce_order_itemmeta.order_item_id = Z.order_item_id
left JOIN wp_woocommerce_order_itemmeta as X
ON wp_woocommerce_order_itemmeta.order_item_id = X.order_item_id
left JOIN wp_comments
ON wp_comments.comment_post_ID = wp_posts.ID
where 1=1
AND wp_woocommerce_order_itemmeta.meta_key ="Adults"
AND wp_postmeta.meta_key ="_billing_first_name"
AND Y.meta_key ="_billing_last_name"
AND Z.meta_key ="Booking Type"
AND Z.meta_value LIKE "%'.$showlocation.'%"
AND X.meta_key ="Booking Date"
AND X.meta_value = "'.$showdate.'"
AND wp_posts.post_status ="wc-completed"
GROUP BY wp_posts.ID
This works
SELECT
wp_woocommerce_order_itemmeta.meta_value AS Adults,
wp_postmeta.meta_value AS FirstName,
jn_postmeta_lastname.meta_value AS LastName,
jn_woocommerce_order_itemmeta_location.meta_value AS Location,
jn_woocommerce_order_itemmeta_date.meta_value AS ShowDate,
(SELECT
GROUP_CONCAT(wp_comments.comment_content)
FROM
wp_comments
WHERE
wp_comments.comment_content NOT LIKE '%status%'
AND wp_comments.comment_post_ID = wp_posts.ID) Notes
FROM
wp_postmeta
LEFT JOIN
wp_postmeta AS jn_postmeta_lastname ON wp_postmeta.post_id = jn_postmeta_lastname.post_id
LEFT JOIN
wp_posts ON wp_postmeta.post_id = wp_posts.ID
LEFT JOIN
wp_woocommerce_order_items ON wp_woocommerce_order_items.order_id = wp_posts.ID
LEFT JOIN
wp_woocommerce_order_itemmeta ON wp_woocommerce_order_itemmeta.order_item_id = wp_woocommerce_order_items.order_item_id
LEFT JOIN
wp_woocommerce_order_itemmeta AS jn_woocommerce_order_itemmeta_location ON wp_woocommerce_order_itemmeta.order_item_id = jn_woocommerce_order_itemmeta_location.order_item_id
LEFT JOIN
wp_woocommerce_order_itemmeta AS jn_woocommerce_order_itemmeta_date ON wp_woocommerce_order_itemmeta.order_item_id = jn_woocommerce_order_itemmeta_date.order_item_id
LEFT JOIN
wp_comments ON wp_comments.comment_post_ID = wp_posts.ID
WHERE
1 = 1
AND (wp_postmeta.meta_key = '_billing_first_name'
AND jn_postmeta_lastname.meta_key = '_billing_last_name'
AND wp_woocommerce_order_itemmeta.meta_key = 'Adults'
AND jn_woocommerce_order_itemmeta_location.meta_key = 'Booking Type'
AND jn_woocommerce_order_itemmeta_location.meta_value LIKE "%'.$showlocation.'%"
AND jn_woocommerce_order_itemmeta_date.meta_key = 'Booking Date'
AND jn_woocommerce_order_itemmeta_date.meta_value = "'.$showdate.'"
AND wp_posts.post_status = 'wc-completed'
GROUP BY wp_posts.ID

mysql query that joins a parent column and has multiple inner joins

I'm using the wordpress / woocommerce database structure and am looking to make a custom query.
Basically I need to grab all products without a certain variation and I'm having trouble joining the IDs.
A product and a product_variation are both posts with associated postmeta.
An example schema:
wp_posts wp_postmeta
ID post_id
post_parent meta_key
post_type meta_value
post_status
An example of the wp_posts table would look like this:
id name post_parent meta_key meta_value
2 tshirt null
3 pants null
4 2 variation_type red
5 2 variation_type blue
Here you can see 4 posts; 2 products and 2 variations. The variation's post_parent point to the product. So i have a red and blue tshirt
What I need, is to grab all products with a blue variation, meaning I need to join post_parent to id.
This is what I have so far.
SELECT * FROM wp_posts wp1
INNER JOIN wp_postmeta pm1
ON (pm1.post_id = wp1.ID)
INNER JOIN wp_postmeta pm2
ON (pm2.post_id = wp1.ID)
JOIN wp_posts wp2
ON (wp2.post_parent = wp1.ID)
AND wp1.post_type = 'product_variation'
AND wp1.post_status = 'publish'
AND pm1.meta_key = 'groups-groups_read_post'
AND pm1.meta_value = 'vet_read'
AND pm2.meta_key = 'variation_type'
AND pm2.meta_value = 'blue'
I believe I'm doing the joins wrong. Any guidance is appreciated.
This process is pretty complicated as there are a lot of things going on under the hood. In a project of mine I have to grab all the post ids (primary product ids) based on a certain attribute.
SELECT
DISTINCT p.post_parent FROM `wp_posts` AS p
LEFT JOIN
`wp_postmeta` AS pm ON p.ID = pm.post_id
LEFT JOIN
`wp_postmeta` AS pm2 ON p.ID = pm2.post_id
WHERE
p.post_type = 'product_variation' AND
(
(pm.meta_key = 'attribute_pa_size' AND pm.meta_value = "XL") OR
(pm.meta_key = 'attribute_size' AND pm.meta_value = "XL")
) AND
pm2.meta_key = '_stock' AND pm2.meta_value != '0'
I had a variation size and I wanted to grab the products who have this variation and is of course not out of stock. You will notice I had to check for the meta_key twice because when you enter attribute in product editor page then woocommerce will store it as attribute_{$attribute_name} and save it in the attributes section. But if you select it from the dropdown of available attributes those are saved previously then you have to look for attribute_pa_{$attribute_name}. I am sure you can modify this SQL based on your requirement.
Note: If you intend to use this custom query alongside with the pre_get_posts to set the post__in parameter then regrettably it won't work. Woocommerce has a filter loop_shop_post_in that overrides this. Just to let you know.
Hope this might help you.
I worked it out and this is what I needed
SELECT wp_posts.* FROM wp_posts
INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id)
LEFT JOIN wp_posts p2 ON (wp_posts.ID = p2.post_parent) AND p2.post_type = 'product_variation'
INNER JOIN wp_postmeta pm2 ON (pm2.post_id = p2.ID) AND pm2.meta_key = 'variation_type' and pm2.meta_value = 'blue'
WHERE wp_posts.post_type = 'product'
AND (wp_posts.post_status = 'publish')
AND (wp_postmeta.meta_key = 'groups-groups_read_post')
AND CAST(wp_postmeta.meta_value AS CHAR) = 'vet_read';

combine two sql queries -

I've have two sql queries which I'm trying to combine
The first:
SELECT * FROM wp_posts
JOIN wp_postmeta on (post_id=ID)
WHERE meta_key = "packageID" and meta_value = 1
ORDER BY post_date limit 50
Joins the wordpress wp_post table to the wp_postmeta and gets all the posts meeting with packageID = 1 (I think it might be an inelegant way of doing it but it works)
The second
SELECT * FROM wp_postmeta
JOIN wp_posts ON (meta_value=ID)
WHERE post_id = 2110
AND meta_key = '_thumbnail_id'
again joins the wp_post table to the wp_postmeta table, so for the post with the id 2110 it successfully gets the thumbnail for that posts. NB 2110 is just an example of an id
In Wordpress a thumbnail is a kind of post. So in this example the text which constitutes post 2110 is a associated with post 2115 - the latter being the thumbnail
What I'm trying to do is get the list as in the first query but also get thumbnails associated with each post
I think I need two joins but I can't see how to do it (being an sql beginner)
NB this will be in a script outside Wordpress so I can't use Wordpress's built-in functions
You can try this one,if there are more than one thumbnails for the post you can get the list of thumbnails separated by comma
SELECT
*,
(SELECT
GROUP_CONCAT(meta_value)
FROM
wp_postmeta
WHERE post_id = wp.ID
AND wpm.meta_key = "_thumbnail_id") AS `thumbnails`
FROM
wp_posts wp
JOIN wp_postmeta wpm
ON (wpm.post_id = wp.ID)
WHERE wpm.meta_key = "packageID"
AND wpm.meta_value = 1
ORDER BY wp.post_date
LIMIT 50
Note : GROUP_CONCAT has a limit to concat characters but you
can increase this limit
To get only one thumbnail you can try this
SELECT
*,
(SELECT
(meta_value)
FROM
wp_postmeta
WHERE post_id = wp.ID
AND wpm.meta_key = "_thumbnail_id" LIMIT 1)
FROM
wp_posts wp
JOIN wp_postmeta wpm
ON (wpm.post_id = wp.ID)
WHERE wpm.meta_key = "packageID"
AND wpm.meta_value = 1
ORDER BY wp.post_date
LIMIT 50
try with the following code
SELECT * FROM wp_posts wp JOIN wp_postmeta wm on (wp.post_id=wm.ID) WHERE wp.meta_key = "packageID" and wp.meta_value = 1 ORDER BY wp.post_date limit 50;
use proper alias and try it.
Try using the post_type column. The attachments have a post_type of 'attachment'. I can further explain if needed.
Also the post to which the thumbnail is attached to will be in the column post_parent.
global $wpdb;
$query7 = "SELECT distinct wp_postmeta.meta_value, wp_postmeta.meta_key, wp_posts.ID
FROM wp_posts INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id)
INNER JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id)
WHERE wp_posts.ID = wp_postmeta.post_id
AND wp_posts.post_status = 'publish'
AND wp_postmeta.meta_key = 'packageID'
AND wp_postmeta.meta_value = 1
AND (mt1.meta_key LIKE '_thumbnail_id')
$output = $wpdb->get_results( $query7 );
Use join with different aliases when joining same table more than once.
Hope this helps.
Try this
SELECT * FROM wp_posts P1
LEFT JOIN wp_postmeta M1 ON (M1.post_id=P1.ID)
WHERE (M1.meta_key = "packageID" and M1.meta_value = 1 )
LEFT JOIN wp_postmeta M2 ON (M2.meta_key=P1.ID AND M2.meta_key = '_thumbnail_id')
LEFT JOIN wp_posts P2 ON (M2.meta_value=P2.ID)
ORDER BY P1.post_date limit 50

Advanced Wordpress MySQL Query selecting products and attributes

I've been at this for the last 6 hours so I figured I'd ask here for help.
My goal is to display all products in the database on a page on the site. The products are domain names and each one has attributes that need to be displayed.
I'm pretty stumped, here's what I've got so far:
SELECT p.id, p.post_title, p.guid,
meta_price.meta_value as price,
mozrank.name as mozrank,
pa.name as pa
FROM wp_posts p
INNER JOIN wp_postmeta meta_price ON p.id=meta_price.post_id
AND meta_price.meta_key='_regular_price'
INNER JOIN wp_postmeta meta_instock ON p.id=meta_instock.post_id
AND meta_instock.meta_key='_stock_status'
INNER JOIN wp_term_relationships relationships ON p.id=relationships.object_id
INNER JOIN wp_term_taxonomy ttmozrank ON ttmozrank.taxonomy='pa_mozrank'
AND ttmozrank.term_taxonomy_id=relationships.term_taxonomy_id
INNER JOIN wp_terms mozrank ON mozrank.term_id=ttmozrank.term_id
INNER JOIN wp_term_taxonomy ttpa ON ttpa.taxonomy='pa_pa'
AND ttpa.term_taxonomy_id=relationships.term_taxonomy_id
INNER JOIN wp_terms pa ON pa.term_id=ttpa.term_id
WHERE p.post_status = 'publish'
AND post_type = 'product'
AND meta_price.meta_value<>''
AND meta_instock.meta_value = 'instock'
GROUP BY p.id
When you remove this block, MySQL outputs what I want but only for one attribute.
INNER JOIN wp_term_taxonomy ttpa ON ttpa.taxonomy='pa_pa'
AND ttpa.term_taxonomy_id=relationships.term_taxonomy_id
INNER JOIN wp_terms pa ON pa.term_id=ttpa.term_id
There are a few attributes I want to show: item-number, pa, da, mozrank, backlinks, referring-domains, tf, cf.
Help would be appreciated greatly :)
Edit: Table Structure
wp_terms
term_id
name
wp_term_taxonomy
term_taxonomy_id
term_id
taxonomy
wp_term_relationships
object_id
term_taxonomy_id
wp_postmeta
post_id
meta_id
meta_key
meta_value
I suggest you change your INNER JOINs to LEFT JOINs. INNER JOIN will remove rows if nothing matches in the table to the left side of the join.
You may also want to recast your ON clauses with parentheses, as follows:
INNER JOIN wp_term_taxonomy ttpa
ON ( ttpa.taxonomy='pa_pa'
AND ttpa.term_taxonomy_id=relationships.term_taxonomy_id)
edit
What purpose does the GROUP BY clause serve? You are using an evil confusing nonstandard MySQL extension to GROUP BY. Read this and understand it, or get rid of GROUP BY. http://dev.mysql.com/doc/refman/5.0/en/group-by-extensions.html Seriously.
There are three things going on in your query, it seems. We need to break this stuff down carefully if we are to have any chance of troubleshooting this thing. Let's use the Structured in Structured Query Language to get this working correctly.
First, you are trying to get a resultset containing particular posts (in your case, items for sale).
SELECT p.id, p.post_title, p.guid
FROM wp_posts p
WHERE p.post_status = 'publish'
AND post_type = 'product'
Does this query yield an appropriate list of items? It may contain some unpriced items or other such things, but it should have, at least, all the items you need in your list.
Second, you are trying to retrieve and display taxonomy information (categories, keywords, etc) for your product posts. Here's a query that fetches that stuff, I think (I don't understand this part of your application as well as you do). I think there are two areas of taxonomy you're trying to pull out. This is the typical WordPress taxonomy lookup hairball. One of them is this:
SELECT tr.object_id AS id,
t.name AS mozrank
FROM wp_term_relationships AS tr
INNER JOIN wp_term_taxonomy AS x
ON (x.taxonomy='pa_mozrank'
AND x.term_taxonomy_id=tr.term_taxonomy_id)
INNER JOIN wp_terms AS t
ON t.term_id=x.term_id
Test this query. It should give a row for every post that's classified in the 'pa_mozrank' taxonomy showing the post id and the mozrank value in that taxonomy. Make sure this query works. If not, figure it out. Do not proceed until you understand this one and have it working.
Ditto ditto for the the query to fetch the value from the pa_pa hierarchy.
SELECT tr.object_id AS id,
t.name AS pa
FROM wp_term_relationships AS tr
INNER JOIN wp_term_taxonomy AS x
ON (x.taxonomy='pa_pa'
AND x.term_taxonomy_id=tr.term_taxonomy_id)
INNER JOIN wp_terms AS t
ON t.term_id=x.term_id
Third, you're retrieving particular attributes from post_meta. We need something similar for posts and prices, and posts and stock status. Again, write these queries and debug them individually. Here's for price.
SELECT post_id AS id, meta_value AS price
FROM wp_postmeta
WHERE meta_key = `_regular_price'
Here's for stock status.
SELECT post_id AS id, meta_value AS stockstatus
FROM wp_postmeta
WHERE meta_key = `_stock_status'
Good: we have five debugged subqueries. Each is indexed on id.
list of published product posts
list of all posts with their pa_mozrank classifications.
list of all posts with their pa_pa classifications.
price.
stocking status.
Now we need to join all this stuff together. Here's the general outline of our final query. Presumably you can see how this relates to your original query.
SELECT whatever
FROM wp_posts AS p
LEFT JOIN (mozranks) AS mo ON p.id = mo.id
LEFT JOIN (pas) AS pa ON p.id = pa.id
LEFT JOIN (prices) AS pr ON p.id = pr.id
LEFT JOIN (stockstatus) AS ss ON p.id = ss.id
WHERE p.post_status = 'publish'
AND p.post_type = 'product'
AND pr.price <> ''
AND ss.stockstatus = 'instock'
We're using LEFT JOIN here because we still want stuff from the wp_posts table even if it is missing some or all of the attributes.
Finally, putting it all together, we get rather a gigantic query. But we get a query in which all the parts of been unit tested. So, we don't have to smack our foreheads and say WTF? WTF? at this stage of creating the query.
SELECT whatever
FROM wp_posts AS p
LEFT JOIN (
SELECT tr.object_id AS id,
t.name AS mozrank
FROM wp_term_relationships AS tr
INNER JOIN wp_term_taxonomy AS x
ON (x.taxonomy='pa_mozrank'
AND x.term_taxonomy_id=tr.term_taxonomy_id)
INNER JOIN wp_terms AS t
ON t.term_id=x.term_id
) AS mo ON p.id = mo.id
LEFT JOIN (
SELECT tr.object_id AS id,
t.name AS pa
FROM wp_term_relationships AS tr
INNER JOIN wp_term_taxonomy AS x
ON (x.taxonomy='pa_pa'
AND x.term_taxonomy_id=tr.term_taxonomy_id)
INNER JOIN wp_terms AS t
ON t.term_id=x.term_id
) AS pa ON p.id = pa.id
LEFT JOIN (
SELECT post_id AS id, meta_value AS price
FROM wp_postmeta
WHERE meta_key = `_regular_price'
) AS pr ON p.id = pr.id
LEFT JOIN (
SELECT post_id AS id, meta_value AS stockstatus
FROM wp_postmeta
WHERE meta_key = `_stock_status'
) AS ss ON p.id = ss.id
WHERE p.post_status = 'publish'
AND p.post_type = 'product'
AND pr.price <> ''
AND ss.stockstatus = 'instock'
That's a long query, but you can see how it's put together pretty easily, and you can debug the parts one by one.
Query optimizers are designed to make this stuff as efficient as it can be, so you don't have to worry about that, unless you have, let's say, millions of items for sale, in which case you're probably amazon.com anyway.
If you were an enterprise developer doing this for a big company, you might use SQL views for the subqueries. (If you were on Oracle or PostgreSQL, you could employ WITH clauses in your queries.) You could even do this in WordPress, but you'd probably want to write a plugin that created and deleted them on activation and deactivation. Just using large SQL queries might be easier.
You have too much joins it will increase your load time.. Please do it like i did it..
SELECT
p1.ID as id,
p1.post_title as title,
p1.post_content as description,
p1.guid as link,
(CASE WHEN pm1.meta_key = '_thumbnail_id' then p2.guid ELSE NULL END) as image_​​link,
(CASE WHEN pm1.meta_key = '_stock_status' then pm1.meta_value ELSE NULL END) as availability,
(CASE WHEN pm1.meta_key = '_sale_price' then pm1.meta_value ELSE NULL END) as sales_price,
(CASE WHEN pm1.meta_key = '_price' then pm1.meta_value ELSE NULL END) as price,
(CASE WHEN pm1.meta_key = '_regular_price' then pm1.meta_value ELSE NULL END) as regular_price
FROM
wp_posts p1
LEFT JOIN
wp_postmeta pm1
ON (
pm1.post_id = p1.ID
)
LEFT JOIN
wp_posts p2
ON (
pm1.post_id = p2.ID
)
WHERE
p1.post_type IN ('product','product_variation')
AND
p1.post_status = 'publish'
GROUP BY p1.ID