I want to select all (WordPress) posts together with the eventual brand and brand_id (both from the same taxonomy). If there is no brand set, the post should be selected anyway with these two fields set as NULL.
This query does almost work, but it's excluding posts that are missing a brand:
SELECT
p.ID AS post_id,
p.post_title AS title,
p.post_content AS body,
brand.name AS brand,
brand.term_id AS brand_id,
UNIX_TIMESTAMP(p.post_date) AS date_added
FROM
wp_posts AS p
INNER JOIN wp_term_relationships AS brand_rel
ON brand_rel.object_id = p.ID
INNER JOIN wp_term_taxonomy AS brand_tax
ON brand_tax.term_taxonomy_id = brand_rel.term_taxonomy_id
AND brand_tax.taxonomy = "product_brand"
INNER JOIN wp_terms AS brand
ON brand.term_id = brand_tax.term_id
WHERE
p.post_type = 'product' AND
p.post_status = 'publish'
GROUP BY post_id;
Changing from INNER JOIN to LEFT JOIN, I get all the posts - but none of their brands (both brand and brand_id are NULL):
SELECT
p.ID AS post_id,
p.post_title AS title,
p.post_content AS body,
brand.name AS brand,
brand.term_id AS brand_id,
UNIX_TIMESTAMP(p.post_date) AS date_added
FROM
wp_posts AS p
LEFT JOIN wp_term_relationships AS brand_rel
ON brand_rel.object_id = p.ID
LEFT JOIN wp_term_taxonomy AS brand_tax
ON brand_tax.term_taxonomy_id = brand_rel.term_taxonomy_id
AND brand_tax.taxonomy = "product_brand"
LEFT JOIN wp_terms AS brand
ON brand.term_id = brand_tax.term_id
WHERE
p.post_type = 'product' AND
p.post_status = 'publish'
GROUP BY post_id;
If I however remove the GROUP BY statement during the LEFT JOIN I seem to get all the posts with and without a brand as I should, but also with alot of duplicates where most of the brand and brand_id fields are NULL.
All help appreciated.
Related
Trying to fetch products ID and the products variable ID in Mysql.
My category is 7006.
This query gives me only the general product, and not the product variables values.
SELECT post.ID, post.post_title, metavalue1.meta_value AS MetaValue1, metavalue2.meta_value AS MetaValue2
FROM wp_posts post
LEFT JOIN wp_postmeta metavalue1 ON post.ID = metavalue1.post_id
AND '_enable_colorlab' = metavalue1.meta_key
LEFT JOIN wp_postmeta metavalue2 ON post.ID = metavalue2.post_id
AND '_wcpa_product_meta' = metavalue2.meta_key
LEFT JOIN wp_term_relationships rs ON rs.object_id = post.ID
WHERE rs.term_taxonomy_id ='7006';
This query gives me all variables ID i need
SELECT post.ID, post.post_title FROM wp_posts post
INNER JOIN wp_postmeta pa ON pa.post_id = post.ID
INNER JOIN wp_term_relationships rs ON rs.object_id = post.ID
WHERE rs.term_taxonomy_id ='7006';
How can i get first query to include all product and variables values and not the general product value?
IT will return variation products with variant id.
SELECT wp.id AS `Product Id`, wpv.id AS `Variant Id`, wp.post_title, wpv.post_title, wpv.post_excerpt
FROM wp_posts wp
INNER JOIN wp_term_relationships r ON wp.ID = r.object_id
INNER JOIN wp_term_taxonomy tt ON r.term_taxonomy_id = 7006
INNER JOIN wp_terms t ON t.term_id = tt.term_id
INNER JOIN wp_posts wpv ON wp.id = wpv.post_parent
LEFT JOIN wp_postmeta wpm ON wp.ID = wpm.post_id
WHERE tt.taxonomy = 'product_type'
AND t.name = 'variable'
AND wpv.post_type != 'attachment'
AND wpm.meta_key = '_enable_colorlab'
You can try something like this:
select
p.id,
p.post_title,
group_concat(concat(m.meta_key, ':', m.meta_value))
from
wp_posts as p
left join wp_postmeta as m on m.post_id = p.id
left join wp_term_relationships rs on rs.object_id = p.id
where
rs.term_taxonomy_id = '7006'
group by
p.id,
p.post_title
In PHP you can explode concatenated string of values
I have an SQL query that properly pulls Product Variations and stock levels, but I don't have the Product Category. How can I add that to this query? I want to pull the single most specific category instead of the parent category, ideally.
SELECT p.ID, p.post_title, p.post_excerpt, p.post_name, pm.meta_key, pm.meta_value
FROM wp_posts p
INNER JOIN wp_postmeta pm ON pm.post_id = p.ID
WHERE p.post_type IN ('product_variation')
AND p.post_status = 'publish'
AND pm.meta_key IN (
'_stock')
ORDER BY p.post_title
Thanks for any help you can offer!
you could try to add some extra inner joins
INNER JOIN wp_term_relationships AS tr ON ('p.ID' = tr.object_id)
INNER JOIN wp_term_taxonomy AS tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id)
INNER JOIN wp_terms AS t ON (t.term_id = tt.term_id)
because the terms/taxonmy uses a pivot(-ish) table to store the terms information of each post.
Is there a reason why you're not using the default WP_Query to get all the products?
The final query I used was:
SELECT p.post_parent, p.ID, p.post_title, p.post_excerpt, p.post_name, pm.meta_key, pm.meta_value, MAX(t.slug)
FROM wp_posts p
INNER JOIN wp_postmeta pm ON pm.post_id = p.ID
INNER JOIN wp_term_relationships AS tr ON (p.post_parent = tr.object_id)
INNER JOIN wp_term_taxonomy AS tt ON (tt.taxonomy = 'product_cat' AND tr.term_taxonomy_id = tt.term_taxonomy_id)
INNER JOIN wp_terms AS t ON (t.term_id = tt.term_id)
WHERE p.post_type IN ('product_variation')
AND p.post_status = 'publish'
AND pm.meta_key IN (
'_stock')
AND pm.meta_value IS NOT NULL
GROUP BY p.post_parent, p.ID, p.post_title, p.post_excerpt, p.post_name, pm.meta_key, pm.meta_value
ORDER BY p.post_title
The only downside is that it may join with the Parent Category instead of the Child category. Ideally it always joins the lowest level child Category so it's most specific.
Sorry Guys I was using a different example, instead of using COuntry table from w3school I updated my question and give you the real situation.
Im using wordpress and I want to filter out all posts with multiple categories.
`SELECT DISTINCT p.id,p.post_title,p.post_content,t.name,tax.taxonomy from
wp_posts as p
LEFT JOIN wp_term_relationships rel ON rel.object_id = p.ID
LEFT JOIN wp_term_taxonomy tax ON tax.term_taxonomy_id =
rel.term_taxonomy_id
LEFT JOIN wp_terms t ON t.term_id = tax.term_id
WHERE 1=1
AND p.post_status = 'publish'
AND p.post_title LIKE '%lorem%'
OR p.post_content LIKE '%lorem%' `
I want to use raw sql because I know that conditions will be longer than that.
Here is what Iam getting
https://d.pr/free/i/mrNHXk
But when I added this
`AND t.name = 'CGN'
AND t.name = 'Harmony'`
I got no result, iam expecting this
https://d.pr/free/i/0NER1F
Using
AND t.name IN ('CGN','Harmony')
Will not work because The result must have both 'cgn' and 'harmony', if I added 'cfw' on the condition like
AND t.name IN ('CGN','Harmony','cfw')
The result post should have those 3 categories
Do not join directly with the taxonomy tables, but use a subquery and the exists predicate to check whether the tags Harmony and CGN exist for the post.
select p.id, p.post_title, p.post_content,
(select GROUP_CONCAT(t.name) from wp_term_relationships rel
inner join wp_term_taxonomy tax ON tax.term_taxonomy_id = rel.term_taxonomy_id
inner join wp_terms t ON t.term_id = tax.term_id
where rel.object_id = p.ID) as terms
from wp_posts as p
where
p.post_status = 'publish'
and (p.post_title LIKE '%lorem%' OR p.post_content LIKE '%lorem%' )
and exists (select * from wp_term_relationships rel
inner join wp_term_taxonomy tax ON tax.term_taxonomy_id = rel.term_taxonomy_id
inner join wp_terms t ON t.term_id = tax.term_id
where rel.object_id = p.ID and t.name = 'Harmony')
and exists (select * from wp_term_relationships rel
inner join wp_term_taxonomy tax ON tax.term_taxonomy_id = rel.term_taxonomy_id
inner join wp_terms t ON t.term_id = tax.term_id
where rel.object_id = p.ID and t.name = 'CGN')
you will not get any results of that query. The reason is that the Country value can't be both 'Germany' and 'USA' at the same time (in a logical/propositional way).
Try:
SELECT * FROM Customers WHERE Country in ('Germany','USA')
other possibility:
SELECT * FROM Customers WHERE Country like '%Germany%' or like '%USA%'
As stated above, the case where country is both Germany and USA shouldn't exist. It would seem you are looking for:
SELECT * FROM Customers
WHERE Country IN ('Germany', 'USA');
Using the IN clause with a list will return all rows in the customer table where the country contains either Germany or USA.
https://www.w3schools.com/sql/trysql.asp?filename=trysql_select_in2
I'm trying to find out the most purchased products but to only count distinct users ids. Basically my client wants to stop duplicate purchases from the same user, so that they can't affect the chart/best sellers.
I need to count all order_items for that product, using only Distinct users ids. Currently the results are counting all order_items so the Distinct isn't working.
Any help and I would be grateful.
Thanks in advance
SELECT *
FROM
( SELECT DISTINCT
order_item_meta_3.meta_value as distinct_user_order_items_id,
order_item_meta_2.meta_value as product_id,
SUM( order_item_meta.meta_value ) as item_quantity
FROM
wp_woocommerce_order_items as order_items
LEFT JOIN wp_woocommerce_order_itemmeta as order_item_meta
ON order_items.order_item_id = order_item_meta.order_item_id
LEFT JOIN wp_woocommerce_order_itemmeta as order_item_meta_2
ON order_items.order_item_id = order_item_meta_2.order_item_id
LEFT JOIN wp_woocommerce_order_itemmeta as order_item_meta_3
ON order_items.order_item_id = order_item_meta_3.order_item_id
LEFT JOIN wp_posts AS posts
ON order_items.order_id = posts.ID
LEFT JOIN wp_term_relationships AS rel
ON posts.ID = rel.object_ID
LEFT JOIN wp_term_taxonomy AS tax
USING( term_taxonomy_id )
LEFT JOIN wp_terms AS term
USING( term_id )
WHERE
posts.post_type = 'shop_order'
AND posts.post_status = 'publish'
AND tax.taxonomy = 'shop_order_status'
AND term.slug IN ('completed','processing','on-hold')
AND order_items.order_item_type = 'line_item'
AND order_item_meta.meta_key = '_qty'
AND order_item_meta_2.meta_key = '_product_id'
AND order_item_meta_3.meta_key = '_user_id'
GROUP BY
order_item_meta_2.meta_value
ORDER BY
item_quantity DESC ) as order_table,
wp_posts
LEFT JOIN wp_postmeta as mk1
ON wp_posts.ID = mk1.post_id
LEFT JOIN wp_postmeta as mk2
ON wp_posts.ID = mk2.post_id
WHERE
order_table.product_id = wp_posts.ID
AND wp_posts.ID = mk1.post_id
AND mk1.meta_key = 'is_album'
AND mk1.meta_value = 0
AND mk2.meta_key = '_price'
AND mk2.meta_value = 0
Wouldn't you need to do the sum outside the group by. you have to materialize the distinct set first then aggregate it...
so change first few lines to...
SELECT distinct_user_order_items_Id, product_Id, sum(item_Quantity) as item_Quantity
FROM (
SELECT
order_item_meta_3.meta_value as distinct_user_order_items_id,
order_item_meta_2.meta_value as product_id,
order_item_meta.meta_value as item_quantity
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