Creating sql query that references a meta value - mysql

Hoping for some help with a sql query. I have the following:
$sql = "SELECT * from
(SELECT m1.post_id as ID,post_date,m1.meta_value as project_name, m2.meta_value as access_key, m3.meta_value as seq_number
FROM wpha_posts
join wpha_postmeta m1 on m1.post_id = ID and m1.meta_key = '_field_5'
join wpha_postmeta m2 on m2.post_id = ID and m2.meta_key = '_field_7'
join wpha_postmeta m3 on m3.post_id = ID and m3.meta_key = '_seq_num'
where post_type = 'nf_sub' AND post_author = ".$profile_id." AND wpha_postmeta.seq_number = ".$seqNumber.") as v1";
$results = $wpdb->get_results($sql);
What I am trying to do is show data that is from two sql tables but only show results where the sequence number matches the number I have passed via the url.
$seqNumber = (int)$_GET['id'];
I am failing at matching with the meta value of the _seq_num meta key in the database.
Any help would be much appreciated

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"

Modifying MySQL Query for WpDataTables

I am building a table in WpDataTables that involves two custom post types: 'applicants' and 'reviews'. I am trying to create a table that shows all of the applicants that have either been reviewed by the current user (reviewer) who is viewing the WpDataTable. Each applicant can have one or more reviews.
This query runs exactly like I want it to in MySQL, however, WpDataTables does not like it for some reason. I believe it is because of the subquery.
SELECT a.ID, r.post_title, a.post_title, a.guid, r.post_type, a.post_type, r.post_author,
b.meta_value review_app_score,
c.meta_value review_app_comment
FROM (SELECT * FROM `wppm_2_posts` WHERE post_author = 1 AND post_type = 'reviews' AND post_status = 'publish') as r
RIGHT JOIN `wppm_2_posts`as a ON r.post_title = a.ID
LEFT JOIN `wppm_2_postmeta` b ON r.ID = b.post_id AND b.meta_key='review_app_score'
LEFT JOIN `wppm_2_postmeta` c ON r.ID = c.post_id AND c.meta_key='review_app_comment'
WHERE a.post_type = 'applicants'
AND a.post_status = 'publish'
Here is what the MySQL results:
https://i.stack.imgur.com/KzvHt.png
This is exactly what I am needing, except I need it to work in WpDataTables.
The reason is that I am looking to take advantage of their dynamic placeholder (%CURRENT_USER_ID%) instead of the '1' in the subquery above for post_author.
Such as:
(SELECT * FROM `wppm_2_posts` WHERE post_author = %CURRENT_USER_ID% AND post_type = 'reviews' AND post_status = 'publish')
Is there another way I could write this without using a subquery? Or there is another way to build this without needing the dynamic placeholder such as PHP?
Any help is appreciated.
Here is the professional way (AKA it wasn't me) of writing the query. Not sure if it will help anyone else but hopefully it will.
SELECT
APPLICANTS.ID AS applicants_id
,APPLICANTS.post_title AS applicants_post_title
,APPLICANTS.guid AS applicants_guid
,APPLICANTS.post_type AS applicants_post_type
,REVIEWS.post_author AS reviews_author_id
,REVIEWS.post_type AS reviews_post_type
,REVIEWS.post_title AS reviews_post_title
,R_APP_SCORES.meta_value AS review_app_score
,R_APP_COMMENTS.meta_value AS review_app_comment
FROM
`%WPDB%posts` AS APPLICANTS
LEFT JOIN
`%WPDB%posts` AS REVIEWS ON
(REVIEWS.post_author = %CURRENT_USER_ID%) AND
(REVIEWS.post_title = APPLICANTS.ID) AND
(REVIEWS.post_type = 'reviews') AND
(REVIEWS.post_status = 'publish')
LEFT JOIN
`%WPDB%postmeta` R_APP_SCORES ON
(R_APP_SCORES.post_id = REVIEWS.ID) AND
(R_APP_SCORES.meta_key = 'review_app_score')
LEFT JOIN
`%WPDB%postmeta` R_APP_COMMENTS ON
(R_APP_COMMENTS.post_id = REVIEWS.ID) AND
(R_APP_COMMENTS.meta_key = 'review_app_comment')
WHERE
(APPLICANTS.post_type = 'applicants') AND
(APPLICANTS.post_status = 'publish')

Wordpress get attachment url using wpdb

How can I modify this query to get the attachment url link to my custom post type.
I have tried several solution from the web but none of them are giving the expected result.
$results = $wpdb->get_results(
"SELECT ID, post_title, {$wpdb->prefix}terms.name, GROUP_CONCAT(meta_value SEPARATOR ', ') AS pictoInfos
FROM {$wpdb->prefix}posts
INNER JOIN {$wpdb->prefix}term_relationships
ON ID = {$wpdb->prefix}term_relationships.object_id
INNER JOIN {$wpdb->prefix}terms
ON {$wpdb->prefix}term_relationships.term_taxonomy_id = {$wpdb->prefix}terms.term_id
INNER JOIN {$wpdb->prefix}postmeta
ON ID = {$wpdb->prefix}postmeta.post_id
WHERE (post_type = 'recette' AND post_status = 'publish')
AND (term_taxonomy_id = {$_GET['data']['id']} AND meta_key IN ( 'kilocalorie', 'difficulte', 'nombre_de_minutes' ) )
GROUP BY ID ORDER BY ID DESC ",
ARRAY_A );

MySQL - alternative for like - regexp?

i have got over one milion record in my database table.
When I use like is very slowly, when i use match against they lost some records.
I create help table:
tag_list
tag_id
tag_name
tag_rel_message
tag_id
messag_id
messages
message_id
message_text
in tag_list i add all words of $message_text - explode(" ", $message_text);
My new query is:
SELECT m.*
FROM tag_rel_messages trm
INNER JOIN messages m ON (trm.message_id = m.message_id)
INNER JOIN tag_list tl ON (trm.tag_id=tl.tag_id
WHERE tl.tag_name REGEXP 'pionas' AND tl.tag_name REGEXP 'website'
GROUP By trm.message_id
But not display any records.
What's wrong with this query?
Maybe i should use something other than REGEXP?
Thanks for help
I'm not sure how one column could match two things at the same time! You can use OR in place of AND, or you can use a single call to REGEXP.
SELECT m.*
FROM tag_rel_messages trm
INNER JOIN messages m ON (trm.message_id = m.message_id)
INNER JOIN tag_list tl ON (trm.tag_id=tl.tag_id
WHERE tl.tag_name REGEXP 'pionas|website'
GROUP By trm.message_id
You need to join with the tag_list and tag_rel_message tables twice to match two different tags.
SELECT m.*
FROM messages AS m
JOIN tag_rel_messages AS trm1 ON m.message_id = trm1.message_id
JOIN tag_list AS t1 ON t1.tag_id = trm1.tag_id
JOIN tag_rel_messages AS trm2 ON m.message_id = trm2.message_id
JOIN tag_list AS t2 on t2.tag_id = trm2.tag_id
WHERE t1.tag_name = 'pionas' AND t2.tag_name = 'website'
Another way to do it is to join with either tag, and count the number of results per message
SELECT m.*
FROM messages AS m
JOIN tag_rel_messages AS trm ON m.message_id = trm.message_id
JOIN tag_list AS t ON t1.tag_id = trm.tag_id
WHERE t.tag_name IN ('pionas', 'website')
GROUP BY m.message_id
HAVING COUNT(*) = 2
This second form is a little easier to generalize to any number of tags. Put all the tags in the IN clause, and change the HAVING clause to match the number of tags.
$words = array('pionas', 'website');
$tags_id = array();
foreach ($words as $key => $val) {
$sql = "SELECT tag_id FROM tag_list WHERE tag_name LIKE '%".$val."%'";
$records = $db->query($sql);
$tags_id[$key] = array_column($records, "tag_id");
}
$inner_array = array();
foreach ($tags_id as $k => $v) {
$short_name = "trm_".$k;
$inner_array[] = " INNER JOIN tag_rel_message as ".$short_name." ON ( ".$short_name.".message_id = m.message_id AND ".$short_name.".tag_id IN (".implode(", ", $v).")) ";
}
$sql = "SELECT DISTINCT m.* FROM messages m".implode(" ", $inner_array);
I think this is the same:
SELECT * FROM messages WHERE message_text like '%pionas%' AND message_text like '%website%'

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.