SQL - Multiple Where in one column - mysql

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

Related

Select only one term_id from taxonomy

I have a custom post type and a taxonomy, where I can put more the one value to the taxonomy, in this case the taxonomy is the city. I want to make a query that the result is the posts that only have ONE value set. Example: I want all posts that the taxnomy is only "term_id = 3" that is "sao-paulo-sp".
But I have some posts that has more than one value set to it, like "sao-paulo-sp, city 2, city 3 city 4, etc" and this kinda of post keep showing up in my results.
SELECT wp.ID, wp.post_title, wt.term_id FROM wp_posts wp
INNER JOIN wp_term_relationships wtr ON (wp.`ID` = wtr.`object_id`)
INNER JOIN wp_term_taxonomy wtt ON (wtr.`term_taxonomy_id` =
wtt.`term_taxonomy_id`)
INNER JOIN wp_terms wt ON (wt.`term_id` = wtt.`term_id`)
WHERE wtt.taxonomy = 'cities'
AND wt.slug = 'sao-paulo-sp'
ORDER BY wp.ID
I would like that the result was the posts that only have "sao-paulo-sp" or "term_id = 3' as his value to the taxonomy cities
If I understand correctly, you want something like this:
SELECT wp.ID, wp.post_title, wt.term_id
FROM wp_posts wp INNER JOIN
wp_term_relationships wtr
ON wp.`ID` = wtr.`object_id` INNER JOIN
wp_term_taxonomy wtt
ON wtr.`term_taxonomy_id` = wtt.`term_taxonomy_id` INNER JOIN
wp_terms wt
ON wt.`term_id` = wtt.`term_id`
WHERE wtt.taxonomy = 'cities'
GROUP BY wp.ID
HAVING COUNT(*) = 1 AND MAX(wt.slug) = 'sao-paulo-sp'
ORDER BY wp.ID;
I am not sure what wt.term_id is doing in the SELECT list.
Srry, my english was not good enough to specify my question, if help anyone I solved my problem doing a NOT IN in a select that has term_id different than tem_id 3.
SELECT wp.ID, wp.post_title, wt.slug
FROM wp_posts wp
INNER JOIN wp_term_relationships wtr ON wp.`ID` = wtr.`object_id`
INNER JOIN wp_term_taxonomy wtt ON wtr.`term_taxonomy_id` =
wtt.`term_taxonomy_id`
INNER JOIN wp_terms wt ON wt.`term_id` = wtt.`term_id`
WHERE wtt.taxonomy = 'cidades'
AND wp.ID NOT IN
(SELECT wp.ID
FROM wp_posts wp
INNER JOIN wp_term_relationships wtr ON wp.`ID` = wtr.`object_id`
INNER JOIN wp_term_taxonomy wtt ON wtr.`term_taxonomy_id` =
wtt.`term_taxonomy_id`
WHERE wtt.taxonomy ='cidades' and wtt.term_id <> 3)
ORDER BY wp.ID

Get Wordpress posts that match 2 different categories via custom SQL statement

I'm looking to write a custom SQL statement that will pull published posts from a Wordpress DB that match 2 different categories.
Category 1 (Static) = "Website-1"
Category 2 (Dynamic) = "News", "Tips", "Recreation", etc.
This is a little out of my realm so any help would be greatly appreciated.This is what I have so far:
select p.* from wp_terms wt
join wp_term_taxonomy t on wt.term_id = t.term_id
join wp_term_relationships wpr on wpr.term_taxonomy_id = t.term_taxonomy_id
join wp_posts p on p.id = wpr.object_id
where
t.taxonomy = 'category' and
wt.name = 'Website-1' and
p.post_status = 'publish'
group by p.id
order by p.post_date desc
limit 10
It will pull the first category no problem but I need it to match on 2 categories.
Any insight would be greatly appreciated.
Thanks!
The solution I came up with:
select p.* from wp_posts p
join wp_term_relationships tr on p.id = tr.object_id
join wp_term_taxonomy tt on tt.term_taxonomy_id = tr.term_taxonomy_id
join wp_terms t on t.term_id = tt.term_id
where p.id in
(select tr2.object_id from wp_term_relationships tr2
join wp_term_taxonomy tt2 on tt2.term_taxonomy_id = tr2.term_taxonomy_id
join wp_terms t2 on t2.term_id = tt2.term_id
where
tt2.taxonomy = 'category' and
t2.name in ('Website-1') and
p.id = tr2.object_id
) and
p.post_status = 'publish' and
tt.taxonomy = 'category' and
t.name in ('News')
group by p.id
order by p.post_date desc
limit 10
I'm sure there's a better way to write this query since it's pretty messy but it works for now.
Try having instead of where after group by. I would add this as question / comment but I don't have enough points... what happens if you switch the order of the categories?

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

Select Post with the term id

I am having a situation where i need to select a post but with where condition as shown :-
Post with both the selected terms at once.
I have tried :-
SELECT p.ID, p.post_title FROM wp_posts p
LEFT JOIN `wp_term_relationships` t
ON p.ID = t.object_id
LEFT JOIN `wp_term_taxonomy` tt
ON t.term_taxonomy_id = tt.term_taxonomy_id
WHERE tt.term_id =86
AND tt.term_id=39
GROUP BY t.object_id
HAVING COUNT( t.term_taxonomy_id ) =2
LIMIT 0,7
Here i want to select a post which is having the term id 86 & 39. These both ids are in same table.
What is the relationship between these tables?
This select works, but I think you can try another way, do you have the TAG instead of the code? Anyway, check this out.
SELECT
p.ID
FROM
wp_posts p
LEFT JOIN wp_term_relationships t ON (p.ID = t.object_id)
WHERE
exists (
SELECT tt.term_taxonomy_id FROM wp_term_taxonomy tt
WHERE tt.term_taxonomy_id = t.term_taxonomy_id
and tt.term_id in(86,39)
)
group by p.ID
having count(p.ID) = 2
Use the IN clause
SELECT p.ID
,p.post_title
FROM wp_posts p
LEFT JOIN 'wp_term_relationships' t ON p.ID = t.object_id
LEFT JOIN 'wp_term_taxonomy' tt ON t.term_taxonomy_id = tt.term_taxonomy_id
WHERE tt.term_id IN (86,39)
GROUP BY t.object_id
HAVING COUNT(t.term_taxonomy_id) = 2 LIMIT 0,7
You can write your where condition as follow:
WHERE tt.term_id in (86,39)

How do I filter tags down to specific categories?

I have this working query here that will retrieve tags used in the last 60 days.
$term_ids = $wpdb->get_results("
SELECT DISTINCT wp_term_taxonomy.term_id, wp_terms.name
FROM wp_term_taxonomy
INNER JOIN wp_term_relationships ON wp_term_taxonomy.term_taxonomy_id = wp_term_relationships.term_taxonomy_id
INNER JOIN wp_posts ON wp_posts.ID = wp_term_relationships.object_id
INNER JOIN wp_terms ON wp_terms.term_id = wp_term_taxonomy.term_id
WHERE wp_term_taxonomy.taxonomy = 'post_tag' AND DATE_SUB(CURDATE(), $show_tags_in_days) <= $wpdb->posts.post_date", ARRAY_A);
What I need to modify this to is tags used in the last 60 days AND in a specific Wordpress category. This will be used on a category page of Wordpress. I've been fiddling with this for awhile and I think I've just got myself all confused. Is there a way to do this with another join or should I run two separate queries?
I managed to figure it out. Here is the query I came up with.
SELECT DISTINCT wp_term_taxonomy.term_id, wp_terms.name FROM wp_terms
INNER JOIN wp_term_relationships ON wp_term_relationships.term_taxonomy_id=wp_terms.term_ID
INNER JOIN wp_term_taxonomy ON wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id
INNER JOIN wp_posts ON wp_posts.ID=wp_term_relationships.object_id
WHERE wp_term_taxonomy.taxonomy = 'post_tag' AND wp_posts.ID IN (
SELECT wp_posts.ID FROM wp_terms
INNER JOIN wp_term_relationships ON wp_term_relationships.term_taxonomy_id=wp_terms.term_ID
INNER JOIN wp_term_taxonomy ON wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id
INNER JOIN wp_posts ON wp_posts.ID=wp_term_relationships.object_id
WHERE wp_term_taxonomy.taxonomy = 'category' AND wp_terms.term_id=$cur_cat_id) LIMIT 10
Here is a more in-depth explanation: http://www.ohthecode.com/wordpress/most-used-tags-in-wordpress/
This query retrieves only taxonomy IDs. It is likely that you are using the $term_ids variable in another query to retrieve the posts that have both a tag from the list in the $term_ids variable and are in the category. In other words, find the place where you are actually retrieving posts and pass in both the $term_ids and the category id you are interested in.
However, since you say that you are doing this on a category template page (say category-mycategory.php), you may not need to do anything additional at all since the category should be passed in automatically.