mySQL: selecting based on several keys in key/value table - php

I'm using Wordpress and trying to select values from one of my own tables that correspond to values in the native wp_postmeta table.
My table is called "wellwishertable" and I would like to find all the ID's (so I can count them) from the wellwisher table where...
1) The wellwishertable 'associatedID' field is in wp_postmeta post_id
2) The wellwishertable 'associatedAuthorID' is the same as a $userID variable
3) The wellwishertable 'permission' is pending
4) The wp_postmeta meta_key 'status' is NOT equal to meta_value 'open'
5) The wp_postmeta meta_key 'freeze' is NOT equal to meta_value 'frozen'
I've got this far...
"SELECT DISTINCT wellwisher.ID FROM wellwishertable wellwisher
INNER JOIN wp_postmeta ON (wellwisher.associatedID = wp_postmeta.post_id)
INNER JOIN wp_postmeta AS mt1 ON (wp_postmeta.post_id = mt1.post_id)
INNER JOIN wp_postmeta AS mt2 ON (wp_postmeta.post_id = mt2.post_id)
WHERE wellwisher.associatedAuthorID=".$userID."
AND wellwisher.permission ='pending'
AND ( (mt1.meta_key = 'status' AND mt1.meta_value != 'open') AND
(mt2.meta_key = 'freeze' AND mt2.meta_value != 'frozen') );
This seems to be 'nearly' working except it doesn't count records that don't have a "freeze" meta_key in the wp_postmeta table. I want it to count any record that isn't "frozen" regardless of whether it exists or not (as long as 'status' isn't 'open').
Could someone point me in the right direction?

Use LEFT JOIN instead of INNER JOIN on mt2, as INNER JOIN will only return results that have an entry there.
In order to avoid requiring mt2.meta_key to always have to equal freeze, move that condition up to the ON clause in your join.
You could also consider using COUNT directly in your query rather than figuring it out later:
"SELECT COUNT(DISTINCT wellwisher.ID) FROM wellwishertable wellwisher
INNER JOIN wp_postmeta ON (wellwisher.associatedID = wp_postmeta.post_id)
INNER JOIN wp_postmeta AS mt1 ON (wp_postmeta.post_id = mt1.post_id)
LEFT JOIN wp_postmeta AS mt2 ON (wp_postmeta.post_id = mt2.post_id)
AND mt2.meta_key = 'freeze'
WHERE wellwisher.associatedAuthorID=".$userID."
AND wellwisher.permission ='pending'
AND ( (mt1.meta_key = 'status' AND mt1.meta_value != 'open') AND
(mt2.meta_value != 'frozen') );
IMPORTANT:
Dumping your $userID directly into your query string could be a big security issue. Please consider using parameterized queries.

Related

Count wordpress posts wth specific category and meta value

I need to know the amount of posts for a given category and meta_values. I dont want to use get posts because that actually retrieves an array of posts objects and i only need to know the amount of posts, i don't need all the overhead of the posts array (the results may be in the order of thousands).
These are the conditions that need to be met:
-Category is "user_stats"
AND
-Meta_key is "start_time" and meta_value is bigger than "y" and smaller than "z"
("y" and "z" are integers)
AND
-Meta_key is "seller_id" and meta_value is "123456778"
What i need is the sql statement to execute it with (the code below doesn't work):
$sql_statements="SELECT count(DISTINCT wp_postmeta.`post_id`)
FROM wp_posts
LEFT JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id)
LEFT JOIN wp_term_relationships ON (wp_posts.ID =
wp_term_relationships.object_id)
LEFT JOIN wp_term_taxonomy ON (wp_term_relationships.term_taxonomy_id
= wp_term_taxonomy.term_taxonomy_id)
WHERE wp_postmeta.meta_key = 'seller_nickname'
AND wp_postmeta.meta_value >= '1523656442'
AND wp_postmeta.meta_value <= '1523656529')";
$query = $wpdb->get_results($sql_statements);
Thanks in advance

How to inner join from another table and order by specific row value?

In WordPress, there are 2 tables: wp_terms and wp_termmeta.
I currently do the following to get the terms and parents etc:
$query = mysqli_query($mysqli, "
SELECT wp_terms.term_id,wp_terms.name, wp_term_taxonomy.parent
FROM wp_terms INNER JOIN wp_term_taxonomy ON wp_terms.term_id = wp_term_taxonomy.term_id
WHERE wp_term_taxonomy.taxonomy = 'post-categories'
ORDER BY name");
However - I need to access the wp_termmeta table, select a row where the term_id is the same and the meta_key is "order" then order by the meta_value of the wp_termmeta, instead of name as it is currently.
How would I do that with the current query?
I don't have wordpress-specific knowledge, but according to your description the query could look like this (I added table aliases for readability, but they are not necessary):
SELECT t.term_id, t.name, tax.parent
FROM wp_terms t
INNER JOIN wp_term_taxonomy tax ON t.term_id = tax.term_id
INNER JOIN wp_termmeta m ON m.term_id = t.term_id AND m.meta_key = 'order'
WHERE tax.taxonomy = 'post-categories'
ORDER BY m.meta_value
The most interesting part here is the join condition of the second join, which contains two conditions: m.term_id = t.term_id AND m.meta_key = 'order'
It first makes sure the term ids are matching and then assures that the meta key of the joined row is actually "order".

MySQL and PHP: Inner join and result

Here is a mysql request:
$requete1 = mysql_query("
SELECT a.post_id, e.meta_value
FROM wp_postmeta as b
INNER JOIN wp_postmeta AS a ON b.post_id = a.post_id
INNER JOIN wp_postmeta AS d ON b.post_id = d.post_id
INNER JOIN wp_postmeta AS e ON b.post_id = e.post_id
WHERE b.meta_key = '_show_hide_sales'
AND b.meta_value = '1'
AND d.meta_key = '_sold_sales'
AND d.meta_value != '3'
AND e.meta_key = '_sales_sort_number'
ORDER BY CAST(e.meta_value as UNSIGNED INTEGER) DESC
LIMIT ".($from-1).", ".($range+1)
);
while($resultat1 = mysql_fetch_array($requete1))
{
$res2= $resultat1['post_id']; // this one is ok
$res3= $resultat1['meta_value']; // this one is ambiguous
};
The search on the post_id ($res2) is ok as it is unambiguous.
But there are three possible meta_keys here:
The one that is related to "_show_hide_sales".
The one that is related to "_sold_sales".
The one that is related to "_sales_sort_number".
But how can I get the meta_value ($res3) that is related to the "_sales_sort_number" meta_key?
My SELECT clearly indicates that I want to retrieve the e.meta_value which should be associated to the "_sales_sort_number" meta_key but it doesn't seem to work.
Thank you for your guidance.

Mysql query ignoring the row if child row from left join table doesn't exists

Hi there so first of all , i'm not that expert in mysql queries. i have tow tables wp_posts and wp_wti_like_post and i'm doing LEFT JOIN on wp_wti_like_post ON wp_posts.ID = wp_wti_like_post.post_id and SUM(wp_wti_like_post.value) < 2 BUT if there is no rowin wp_wti_like_post with id of post from wp_posts then it doesn't show even the row from wp_posts and just ignore it , please help in this really need it.
query:
SELECT *
FROM wp_posts
LEFT JOIN wp_wti_like_post ON wp_posts.ID = wp_wti_like_post.post_id
WHERE wp_posts.post_status = 'publish'
GROUP BY wp_wti_like_post.post_id
HAVING SUM( wp_wti_like_post.value ) <2
OR SUM( wp_wti_like_post.value ) = NULL
LIMIT 0 , 200
table wp_wti_like_post
http://prntscr.com/6xixrd
table wp_posts
http://prntscr.com/6xixzp
You might need to restructure your query to as follows:
SELECT * FROM
(
SELECT WP.*, SUM(LP.value) AS `value`
FROM wp_posts WP
LEFT JOIN
(SELECT post_id FROM wp_wti_like_post WHERE post_status = 'publish') LP
ON WP.ID = LP.post_id
GROUP BY WP.ID
) T1
WHERE T1.value IS NULL
OR T1.value < 2;
The Inner-most query first fetches only wti_like_posts that have been published.
The left-join is then performed, which will give you the expected result of fetching all rows from wp_posts, even if they do not join with a record from the sub-query.
After that is performed, the GROUP statement performs the computation of SUMming the values.
The outer-most query enforces the requirement that the sum must either be less than 2 or be null.
So i sorted this out by my self and go it working in this way
at the place of
SUM( wp_wti_like_post.value ) = NULL
it should need to be
SUM( wp_wti_like_post.value ) IS NULL

Getting the average number from a meta value in wp

i've creating following wordpress query which output which is counting the records. However all posts does also have a meta_key with the name betting_odds where the meta_value is something like 2.05, 3.30
how can i add the average values of this meta_key into following query?
SELECT count(DISTINCT $wpdb->postmeta.`post_id`)
FROM $wpdb->posts
LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id)
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->postmeta.meta_key = 'betting_status'
AND $wpdb->postmeta.meta_value != 'Ikke afgjort'
AND $wpdb->posts.post_status = 'publish'
AND $wpdb->term_taxonomy.taxonomy = 'category'
AND $wpdb->term_taxonomy.term_id = 106
This is a common challenge when retrieving data from a key/value store like wp_postmeta.
The trick is to put both the post_id and the meta_key into the ON clause, like so.
(It's also helpful to use table aliases (in this case posts, stat, odds, etc.) in WordPress queries because they get quite a bit more readable.
SELECT count(DISTINCT posts.ID), AVG(odds.meta_value)
FROM $wpdb->posts posts
LEFT JOIN $wpdb->postmeta stat
ON posts.ID = stat.post_id
AND stat.meta_key = 'betting_status'
LEFT JOIN $wpdb->postmeta odds
ON posts.ID = odds.post_id
AND odds.meta_key = 'betting_odds'
LEFT JOIN $wpdb->term_relationships tr ON posts.ID = tr.object_id
LEFT JOIN $wpdb->term_taxonomy t ON tr.term_taxonomy_id = t.term_taxonomy_id
WHERE stat.meta_value != 'Ikke afgjort'
AND posts.post_status = 'publish'
AND t.taxonomy = 'category'
AND t.term_id = 106
Do you see how we are LEFT JOINing the postmeta table twice, once for each meta value we need?? Do you see how the meta_key match criterion goes into the ON clause, not the WHERE clause? That's the pattern to pull meta values for posts.

Categories