SQL WordPress Custom Query Inner Join - mysql

I'm having some difficulty with my SQL statement. I'm doing a query on WordPress to display posts based on multiple post meta fields. When I do the query and filter with only one meta field, or a OR on multiple it works, however AND on multiple fails.
SELECT wposts . *
FROM wp_posts wposts
INNER JOIN (
SELECT post_id
FROM wp_postmeta wpostmeta
WHERE (
(wpostmeta.meta_key = 'ulnooweg_business_industry'
AND wpostmeta.meta_value = 'Legal Services')
AND (
wpostmeta.meta_key = 'ulnooweg_business_province'
AND wpostmeta.meta_value = 'New Brunswick')
)
GROUP BY post_id
)
AS t ON t.post_id = wposts.ID
WHERE wposts.post_status = 'publish'
AND wposts.post_type = 'business'
ORDER BY wposts.post_title ASC
LIMIT 0 , 30

Your query is testing if meta_key (and meta_value) is 2 different values in the same row, which is impossible. But I see what you are trying to do..
Try joining the wp_postmeta table twice except each with an ON clause that excludes all rows except those that satisfy the meta_key condition:
SELECT
p.*,
GROUP_CONCAT(CONCAT(pm.meta_key,':',pm.meta_value) SEPARATOR ',') AS meta_values
FROM
wp_posts p
JOIN wp_postmeta pm ON pm.post_id = p.ID
JOIN wp_postmeta pm_bi ON (pm_bi.post_id = p.ID AND pm_bi.meta_key = 'ulnooweg_business_industry')
JOIN wp_postmeta pm_bp ON (pm_bp.post_id = p.ID AND pm_bp.meta_key = 'ulnooweg_business_province')
WHERE
pm_bi.meta_value = 'Legal Services'
AND pm_bp.meta_value = 'New Brunswick'
AND p.post_type = 'business'
AND p.post_status = 'publish'
GROUP BY p.ID
ORDER BY p.post_title ASC
Note: I joined the wp_postmeta table 3 times here to help prove that the conditions are satisfied, but you can remove the GROUP_CONCAT line (and the comma on the previous line of course) and the first JOIN to wp_postmeta and the query will work the same.

In the subquery, it looks like it's looking for records where both wpostmeta.meta_key = 'ulnooweg_business_industry' and wpostmeta.meta_key = 'ulnooweg_business_province' -- in other words, wpostmeta.meta_key needs to be equal to two strings simultaneously to satisfy this condition. Also, it's looking for wpostmeta.meta_value = 'Legal Services' and wpostmeta.meta_value = 'New Brunswick'.
My guess is that this is what you want in the WHERE clause of the subquery -- change one of the ANDs to an OR:
....
WHERE (
(wpostmeta.meta_key = 'ulnooweg_business_industry'
AND wpostmeta.meta_value = 'Legal Services')
OR ( -- changed to an OR
wpostmeta.meta_key = 'ulnooweg_business_province'
AND wpostmeta.meta_value = 'New Brunswick')
)
....

The problem is in the where clause of your inner select; I'm guessing wpostmeta returns MULTIPLE rows. A previous comment that a string can't be two values is correct. The 2nd approach should work if the 1st doesn't
at first I thought
WHERE
((wpostmeta.meta_key = 'ulnooweg_business_industry' AND wpostmeta.meta_value = 'Legal Services') OR
(wpostmeta.meta_key = 'ulnooweg_business_province' AND wpostmeta.meta_value = 'New Brunswick'))
Group by Post_ID
HAVING count(post_ID) = 2
This will work ONLY if there is only one record in the wpostmeta for each type of entry. If
postmeta.meta_key = 'ulnooweg_business_industry' AND wpostmeta.meta_value = 'Legal Services' can occur twice, then the above does't work.
2nd approach
Select wposts.*
FROM WP_Posts wposts
INNER JOIN (
Select POST_ID from WP_POSTMeta where meta_key = 'ulnooweg_business_industry' AND wpostmeta.meta_value = 'Legal Services'
INTERSECT
SELECT POST_ID FROM WP_POST_META WHERE meta_key = 'ulnooweg_business_province' AND wpostmeta.meta_value = 'New Brunswick'
)
AS T on T.Post_ID = wposts.ID

Related

sort the table based on price store in wp_option

I am working with sql query to get post ids of the product based on multiple table joining which working ok, Now I am try add the sort based on price, price is save in the wp_postmeta
table as meta_key and value. Problem is joining have already condition where we are using different set of meta_key and value. And I am not clear how to add the sort on it, what ever attempt I did I get zero result.
Here is the original query which is working ok.
$args_sql = "SELECT wordpress_posts.ID as ID FROM wordpress_posts INNER JOIN wordpress_term_relationships ON (wordpress_posts.ID = wordpress_term_relationships.object_id) INNER JOIN wordpress_postmeta ON (wordpress_posts.ID = wordpress_postmeta.post_id) INNER JOIN wordpress_postmeta AS mt1 ON (wordpress_posts.ID = mt1.post_id) INNER JOIN wordpress_postmeta AS mt2 ON (wordpress_posts.ID = mt2.post_id) WHERE 1 = 1 AND (wordpress_term_relationships.term_taxonomy_id IN ($txt1)) AND wordpress_posts.post_author NOT IN ($disable_store_txt) AND (wordpress_postmeta.meta_key = 'my_pricing_structure' AND (mt1.meta_key = 'meta_product_type' AND mt1.meta_value != 'auction') AND ((mt2.meta_key = 'meta_ship_to_country_1' AND mt2.meta_value = 'india') OR (mt2.meta_key = 'meta_ship_to_country_2' AND mt2.meta_value = 'india') OR (mt2.meta_key = 'meta_ship_to_country_3' AND mt2.meta_value = 'india') OR (mt2.meta_key = 'meta__ship_to_country_4' AND mt2.meta_value = 'india'))) AND wordpress_posts.post_type = 'my-products' AND ((wordpress_posts.post_status = 'publish')) GROUP BY mt2.post_id ORDER BY wordpress_posts.post_date DESC";
now I add sort on meta_key "original_price"

Wordpress - MySQL query to show posts only from a specific category

I have the following query that bring the posts that contain a specific word in the title
SELECT posts_post.ID AS post_ID,
posts_post.post_date AS post_post_date,
CONCAT('',posts_post.post_title,'') AS post_title_with_link_to_post
FROM wp_posts AS posts_post
WHERE 1=1
AND posts_post.post_title LIKE '%HOTARAR%'
AND posts_post.post_type = 'post'
GROUP BY post_post_date
The problem now is that I need to bring the posts only from a specific category (tag slug for the category is hotarari-consiliu-local and has the ID 160), how could I modify the above query to bring posts only from a single blog posts category? Thanks!
Try the below query.
global $wpdb;
$make = $wpdb->get_results("
SELECT * FROM
$wpdb->posts
LEFT JOIN
$wpdb->term_relationships
ON
($wpdb->posts.ID = $wpdb->term_relationships.object_id)
LEFT JOIN
$wpdb->term_taxonomy
ON
($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)
WHERE
$wpdb->posts.post_type = 'post'
AND
$wpdb->posts.post_title LIKE '%HOTARAR%'
AND
$wpdb->term_taxonomy.taxonomy = 'category'
AND
$wpdb->term_taxonomy.term_id = 160
ORDER BY
post_date DESC
");
Assuming Bhautik is on the right path, then something like this should work (I don't know where 'hotarari-consiliu-local' belongs in this).
SELECT p.ID post_ID
, p.post_date post_post_date
, CONCAT('',p.post_title,'') post_title_with_link_to_post
FROM wp_posts p
JOIN wp_term_relationships pt
ON pt.object_id = p.ID
JOIN wp_term_taxonomy t
ON t.term_taxonomy_id = pt.term_taxonomy_id
WHERE p.post_type = 'post'
AND p.post_title LIKE '%HOTARAR%'
AND t.taxonomy = 'category'
AND t.term_id = 160
ORDER
BY post_date DESC

Multiple Meta_Key Select on on Wordpress database

I've developed a query which selects events from Wordpress. I am using the where clause to select where the meta_value of the meta_key eventstartdate is after today.
The issue I'm having now is, I also want filter on a second meta_value that being from the meta_key '_VenueCity'.
I have tried aliasing the wp_postmeta table and doing a where on the meta_key but I think I'm missing a join.
This is the code that works without my additional code to get it to work. Can any one advise on how I get this to work?
SELECT
`wp_posts`.`ID` AS `EventID`,
`wp_posts`.`post_parent` AS `SeriesID`,
`wp_posts`.`post_title` AS `EventTitle`,
`wp_posts`.`post_content` AS `EventDescription`,
`wp_posts`.`post_excerpt` AS `EventSummary`,
`wp_posts`.`post_name` AS `EventSlug`,
min(`wp_postmeta`.`meta_value`) AS `EventStartDate`,
max(`tribe_event_end_date`.`meta_value`) AS `EventEndDate`,
`wp_posts`.`guid` AS `GUID`
FROM ((`wp_posts`
JOIN `wp_postmeta` ON
(
(`wp_posts`.`ID` = `wp_postmeta`.`post_id`)
))
LEFT JOIN `wp_postmeta` `tribe_event_end_date` ON
(
(
(`wp_posts`.`ID` = `tribe_event_end_date`.`post_id`) AND
(`tribe_event_end_date`.`meta_key` = '_EventEndDate')
)
))
WHERE
(
(`wp_postmeta`.`meta_key` = '_EventStartDate') AND
(`wp_posts`.`post_type` = 'tribe_events') AND
(`wp_posts`.`post_status` = 'publish') AND
(`tribe_event_end_date`.`meta_value` >= CURDATE())
)
GROUP BY
`wp_posts`.`ID`
ORDER BY
`EventStartDate`,
`wp_posts`.`post_date`;
I am not going to write your query for you but I will give an example of how to get multiple postmeta values. The power will be in the where clause to get the right values.
You should also consider what joins you want to use.
SELECT
p.post_title,
pm1.meta_value,
pm2.meta_value
FROM wp_posts as p
INNER JOIN wp_postmeta as pm1
ON p.ID = pm1.post_id
INNER JOIN wp_postmeta as pm2
ON p.ID = pm2.post_id
WHERE
pm1.meta_key = '_my_postmeta_field1'
AND
pm2.meta_key <> '_not_this_field'

How do I perform a between Query on a DB that all ready has multiple joins?

I am trying to write a query to check if the custom meta values in a custom post type(properties) when saved equals the meta values in another custom post type(alerts)
I can get this work for normal match fields however I am trying to get it to work for a range for example, if 'bedrooms' in 'properties' is between 'a_bedrooms_min' and 'a_bedrooms_max' in 'alerts'. My Query looks like this so far:
//Property Meta Fields
$meta_type = 'flat';
$meta_bedrooms = '2';
//Alert Meta Fields
a_bedrooms_min = 1
a_bedrooms_max = 3
SELECT ID
FROM wp_posts
INNER JOIN wp_postmeta m1
ON ( wp_posts.ID = m1.post_id )
INNER JOIN wp_postmeta m2
ON ( wp_posts.ID = m2.post_id )
INNER JOIN wp_postmeta m3
ON ( wp_posts.ID = m3.post_id )
WHERE
wp_posts.post_type = 'alerts'
AND wp_posts.post_status = 'publish'
AND ( m1.meta_key = 'a_property_type' AND m1.meta_value = '$meta_type' )
AND ( m2.meta_key = 'a_bedrooms_min' AND m2.meta_value >= '$meta_bedrooms' )
AND ( m3.meta_key = 'a_bedrooms_max' AND m3.meta_value <= '$meta_bedrooms' )
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date
DESC;
The last two ANDs obviously will not work with what I am trying to do but how would can get this to work?
Thanks
Robert
I think you are close. you have a hybrid old ANSI vs more explicit JOIN. As you can see in this example, each one of the 3 criteria is joined to the meta table on all 3 parts explicitly. So, the ID should only appear ONCE per ID as each of the meta SHOULD AT MOST return one record, and the record will only qualify if all 3 meta find the respective match.
SELECT
ID
FROM
wp_posts
INNER JOIN wp_postmeta m1
ON wp_posts.ID = m1.post_id
AND m1.meta_key = 'a_property_type'
AND m1.meta_value = '$meta_type'
INNER JOIN wp_postmeta m2
on wp_posts.ID = m2.post_id
AND m2.meta_key = 'a_bedrooms_min'
AND m2.meta_value <= '$meta_bedrooms'
INNER JOIN wp_postmeta m3
on wp_posts.ID = m3.post_id
AND m3.meta_key = 'a_bedrooms_max'
AND m3.meta_value >= '$meta_bedrooms'
WHERE
wp_posts.post_type = 'alerts'
AND wp_posts.post_status = 'publish'
GROUP BY
wp_posts.ID
ORDER BY
wp_posts.post_date DESC;
I've revised as I believe the <= and >= were actually backwards. For example, your MINIMUM bedrooms from the meta_value was 1 and max is 3... you are LOOKING for 2 to be qualified.
So, you NEED MIN_BEDROOMS <= 2 and the 2 <= MAX_BEDROOMS
what was originally presented is MIN_BEDROOMS >= 2 (1 is never greater than 2)
and MAX_BEDROOMS <= 2 (2 is never less than 2).
Try again.

How do I optimize this query?

SELECT DISTINCT wposts.*
FROM wp_2_posts wposts, wp_2_postmeta wpostmeta, wp_2_postmeta wpostmeta1, wp_2_term_taxonomy, wp_2_terms, wp_2_term_relationships
WHERE wposts.ID = wpostmeta.post_id
AND wp_2_terms.term_id = '8'
AND wp_2_term_taxonomy.term_id = wp_2_terms.term_id
AND wp_2_term_taxonomy.term_taxonomy_id = wp_2_term_relationships.term_taxonomy_id
AND wp_2_term_relationships.object_id = wposts.ID
AND wpostmeta.meta_key = 'validity'
AND wpostmeta.meta_value > '".$logic_date."'
AND wpostmeta1.meta_key != 'permanent'
AND wposts.post_status = 'publish'
AND wposts.post_type = 'post'
ORDER BY wposts.post_date DESC
Good advice so far, heres the 'evolved' query which still does not use the second meta_key != 'permanent_listing'
SELECT wposts.*
FROM wp_2_posts wposts LEFT JOIN wp_2_postmeta wpostmeta ON wposts.ID = wpostmeta.post_id
LEFT JOIN wp_2_term_relationships wrelationships ON wrelationships.object_id = wposts.ID
LEFT JOIN wp_2_term_taxonomy wtaxonomy ON wtaxonomy.term_taxonomy_id = wrelationships.term_taxonomy_id
LEFT JOIN wp_2_terms wterms ON wtaxonomy.term_id = wterms.term_id
WHERE
wterms.term_id = '--category id here--' AND
wpostmeta.meta_key = 'wpx_validity' AND
wpostmeta.meta_value > '--todays date here--' AND
wpostmeta.meta_key != 'permanent_listing' AND
wposts.post_status = 'publish' AND
wposts.post_type = 'post'
ORDER BY wposts.post_date DESC
LEFT JOIN and INNER JOIN seem to do the same thing.
the following indexes exist: wp_2_terms.term_id, wp_term_taxonomy.term_taxonomy_id, wp_2_term_relationships.object_id
wp_2_postmeta has a meta_id index, and fields: post_id, meta_key, meta_value.
this query is running on WPMU.
At first I recommend that you use the INNER JOIN syntax to join the tables:
SELECT table1.c1, table2.c2 FROM table1
INNER JOIN table2 ON table1.ck = table2.ck
Also you should avoid using the * operator and carefully select the columns you need. DISTINCT also slows down your query. Do you really need it?
First, your wpostmeta1 does not join with anything.
Second, you don't need DISTINCT here, you need IN.
Try this:
SELECT wposts.*
FROM wp_2_posts wposts
JOIN wp_2_postmeta wpostmeta
ON wpostmeta.post_id = wposts.ID
AND wpostmeta.meta_key = 'validity'
AND wpostmeta.meta_value > '".$logic_date."'
JOIN wp_2_postmeta wpostmeta1,
ON wpostmeta1.post_id = wposts.ID
AND wpostmeta1.meta_key != 'permanent'
WHERE wposts.ID IN
(
SELECT wp_2_term_relationships.object_id
FROM wp_2_term_relationships
JOIN wp_2_term_taxonomy
ON wp_2_term_taxonomy.term_taxonomy_id = wp_2_term_relationships.term_taxonomy_id
WHERE wp_2_term_taxonomy.term_id = '8'
)
AND wposts.post_status = 'publish'
AND wposts.post_type = 'post'
ORDER BYc
wposts.post_date DESC
Create the following indexes (or make sure they exist):
wp_2_term_relationships (object_id, term_taxonomy_id)
wp_2_term_taxonomy (term_taxonomy_id, term_id)
wp_2_posts (post_status, post_type, post_date, id)
if the query is too slow,
there are different solutions.
First of all try to create some indexes,
then try to reduce the joins filtering the some of the data with php.
if it is still slow, probably the Database schema is wrong and should be changed.
I'll bet you $5 it is an indexing problem. The first thing I'd do is make sure all the fields you are joining the tables on are indexed.