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
I have complex SELECT request:
select meta_value
from wp_posts v
left join wp_postmeta pm on (pm.post_id = v.id)
left join wp_posts p on (v.post_parent = p.id)
where meta_key in ('_price','_regular_price')
and v.post_type = 'product_variation'
and p.id = '1743'
limit 0,100
It returns me 4 (four) needed fields with values like
400
500
300
350
I need to update these values and set their values equal, for example 1000.
Can I, based on my SELECT, run an UPDATE query?
Any condition used in a Select query could be used in Update query, of course it might need a little modification. What you can do in your case is the following:
meta_value
Update wp_posts
set meta_value = 1000
where id IN (select v.id
from wp_posts v
left join wp_postmeta pm on (pm.post_id = v.id)
left join wp_posts p on (v.post_parent = p.id)
where v.meta_key in ('_price','_regular_price')
and v.post_type = 'product_variation'
and p.id = '1743')
Please note that I didn't test this, so I am not totally sure it will work. Make sure to backup your database before any queries like this. Hopefully it will give you the desired results.
Edit: I have assumed that id in wp_posts is a unique value.
How do I rewrite the query below to avoid the error "You can't specify target table for update in FROM clause"?
UPDATE wp_postmeta
SET meta_value = meta_value + 'A' WHERE (SELECT post_title FROM wp_posts A
LEFT JOIN wp_postmeta B ON B.post_id = A.id WHERE A.post_type = 'player' AND
B.meta_key ='_yoast_wpseo_metadesc') = 'Eric Bledsoe'
This is a MySQL limitation. You can use a join instead. This is one guess on what you intend with your query:
UPDATE wp_postmeta pm JOIN
wp_posts p
ON pm.post_id = p.id AND
p.post_type = 'player' AND
pm.meta_key ='_yoast_wpseo_metadesc'
SET pm.meta_value = CONCAT(pm.meta_value, 'A')
WHERE p.post_title = 'Eric Bledsoe';
As mentioned in the comment, your query either updates all rows in wp_postmeta or none of them. The subquery has no correlation clause to the outer query.
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
After an importing error, there is many duplicate content from my posts.
Then, I try to delete this posts with that query :
DELETE
FROM wp_posts USING wp_posts
LEFT JOIN wp_postmeta pm ON wp_posts.ID = pm.post_id
AND pm.meta_key="_wpbdp[fields][6]"
LEFT JOIN wp_wpbdp_listing_fees wlf ON wp_posts.ID = wlf.listing_id
WHERE wp_posts.post_type="wpbdp_listing"
AND wp_posts.post_status="publish"
AND EXISTS (
SELECT NULL
FROM wp_posts p2
LEFT JOIN wp_postmeta pm2 ON p2.ID = pm2.post_id
AND pm2.meta_key="_wpbdp[fields][6]"
LEFT JOIN wp_wpbdp_listing_fees wlf2 ON p2.ID = wlf2.listing_id
WHERE p2.post_type="wpbdp_listing"
AND pm2.meta_value=pm.meta_value
AND p2.post_status="publish"
AND wlf2.category_id=wlf.category_id
)
Unfortunately, I can't do a SELECT statement who calls the same table that I want to delete.
Is there another solution ?
I tried something new, and it passed.
Following the #Nick's idea, I did that query :
DELETE p
FROM wp_posts p, wp_posts p2
WHERE p.post_title = p2.post_title
AND p.post_type="wpbdp_listing"
AND p2.post_type="wpbdp_listing"
AND p2.post_status="publish"
AND p.post_status="publish"
AND EXISTS(
SELECT NULL
FROM wp_wpbdp_listing_fees wlf
WHERE p.ID = wlf.listing_id
AND EXISTS (
SELECT NULL
FROM wp_wpbdp_listing_fees wlf2
WHERE wlf2.category_id = wlf.category_id
AND p.ID = wlf2.listing_id
)
)
AND EXISTS(
SELECT NULL
FROM wp_postmeta pm
WHERE p.ID = pm.post_id
AND pm.meta_key="_wpbdp[fields][6]"
AND EXISTS (
SELECT NULL
FROM wp_postmeta pm2
WHERE pm2.meta_key="_wpbdp[fields][6]"
AND p.ID = pm2.post_id
AND pm2.meta_value=pm.meta_value
)
)
AND p.ID < p2.ID
It's very ugly and not optimised, but it works !
By the way, thanks for your answers !