Getting All Unique Post Meta Values of a Meta Key - php

I need to retrieve a unique set of meta values of a specific meta key. I found a function from Paul Chimoy which does nearly what I am looking for. I just need 1). a version with a secondary qualification, and 2). a version with a secondary and tertiary qualification in order for it to output what I need.
The function outputs all the meta values for meta_key 'trees' and 'states' but I need to be able to output, 1). all unique meta values for meta_key 'trees' where meta_key 'states' equals 'california' and 2). all unique values for meta_key 'trees' where meta_key 'states' equals 'california' and meta_key 'countries' equals 'usa'.
Trees
meta_key = trees
meta_value = pine, oak, sequoia
States
meta_key = states
meta_value = california, washington, florida
Countries
meta_key = countries
meta_value = usa, uk, ireland
Without success, I adjusted the function to include:
AND (pm.meta_key = 'states' AND pm.meta_value = 'california')
Here is the original function without my additional qualification:
function get_unique_post_meta_values( $key = 'trees', $type = 'post', $status = 'publish' ) {
global $wpdb;
if( empty( $key ) )
return;
$res = $wpdb->get_col( $wpdb->prepare( "
SELECT DISTINCT pm.meta_value FROM {$wpdb->postmeta} pm
LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id
WHERE pm.meta_key = '%s'
AND p.post_status = '%s'
AND p.post_type = '%s'
", $key, $status, $type ) );
return $res;
}
My limited knowledge is not allowing me to properly adjust the function to my needs. I appreciate any help that can be provided to achieve my goals.
Thanks in advance.

I know this is old, and you probably are not looking anymore, but if someone else needs this, here is what needs to be done.
Right now your select statement is:
SELECT DISTINCT pm.meta_value FROM {$wpdb->postmeta} pm
LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id
WHERE pm.meta_key = '%s'
AND p.post_status = '%s'
AND p.post_type = '%s'
That will select the meta value based on one key.
Instead you want to get the unique meta values of another key based on one key.
To do this you need to select the post, then select other distinct meta values based on your required key. This means you need to nest your SQL, and grab your post ID.
SELECT DISTINCT pm.meta_value FROM {$wpdb->postmeta} pm WHERE pm.post_id IN
(SELECT pm.post_id FROM {$wpdb->postmeta} pm
LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id
WHERE pm.meta_key = '%s'
AND pm.meta_value = '%s'
AND p.post_status = '%s'
AND p.post_type = '%s')
AND pm.meta_key = '%s'
Your wrapping statement should look something like:
$res = $wpdb->get_col( $wpdb->prepare($sql, $searchkey, $searchvalue, $poststatus, $posttype, $findkey ) );
Assuming you feed in the SQL above, trees, pine, post, publish, states - you should retrieve a list of states where pine trees grow.
Hope this helps anyone who stumbles upon this!

Related

SQL Search if contains keyword random

I working on my search function and I have an Issue
My query:
$query = " SELECT p.ID, p.post_title
FROM $posts p
LEFT JOIN $postmeta pm ON (pm.post_id = p.ID AND pm.meta_key = '_sku')
WHERE p.post_type = 'product'
AND (
p.ID LIKE '%$keywords%' OR
p.post_title LIKE '%$keywords%' OR
IF(pm.meta_value IS NULL, 0, pm.meta_value LIKE '%$keywords%')
)
ORDER BY p.post_title";
In the column post_title I have a value like Remy Martin XO
Now you can search on Remy or Martin or Remy Matin and there are results.
But if you search on Martin Remy there are no results.
What I tried so far:
I changed the query and replaced the LIKE to CONTAINS but now I have no results on any search
$query = " SELECT p.ID, p.post_title
FROM $posts p
LEFT JOIN $postmeta pm ON (pm.post_id = p.ID AND pm.meta_key = '_sku')
WHERE p.post_type = 'product'
AND (
p.ID LIKE '%$keywords%' OR
--> CONTAINS(p.post_title, '$keywords') <-- OR
IF(pm.meta_value IS NULL, 0, pm.meta_value LIKE '%$keywords%')
)
ORDER BY p.post_title";
Who can help me with this?
Please replace your line with this line. Hopefully it will work.
CONTAINS(p.post_title, '$keywords',1) > 0
If it is my SQL then use INSTR(str,substr). You can search this Syntex you will get lots of example.

SQL join table result of 2 statements

I am trying to get data with SQL from my Wordpress database by a JOIN, but I do not get it working.
What I need:
Posts where the meta_key "gtp_product_dont_show" exists and where the meta_value not is "true".
And posts where the meta_key "gtp_product_dont_show" does not exists.
My Problem:
I now only get the results where posts have a meta_key "gtp_product_dont_show", but there are also posts which don't have this key, and I need these as well.
This is what I have now:
SELECT
ID, post_title
FROM
wp_posts p
JOIN wp_postmeta m ON
p.ID = m.post_id AND
m.meta_key = 'gtp_product_dont_show' AND
m.meta_value != 'true'
WHERE
post_type = 'products' AND
post_status = 'publish'
Output:
You need a left join:
SELECT ID, post_title
FROM wp_posts p LEFT JOIN
wp_postmeta m
ON p.ID = m.post_id AND
m.meta_key = 'gtp_product_dont_show'
WHERE (m.meta_value is null or m.meta_value <> 'true') and
post_type = 'products' AND
post_status = 'publish';
The left join looks for an appropriate key in the wp_postmeta table. The where clause then says "keep a record when there is no match or the value is not true" -- which I think is the logic you are looking for.
You're looking for this?
SELECT
ID, post_title
FROM
wp_posts p
WHERE
post_type = 'products' AND
post_status = 'publish' AND
not exists (
select 1
from wp_postmeta m
where
p.ID = m.post_id AND
m.meta_key = 'gtp_product_dont_show' AND
m.meta_value = 'true')
This will fetch all the rows from wp_posts, but leave out those where row is found from wp_postmeta where meta_key is gtp_product_dont_show and value is true.
You can use the OR operator to consider both conditions. Try this:
SELECT stuff
FROM myTable
JOIN otherTable ON
(m.meta_key = 'gtp_product_dont_show' AND m.meta_value != 'true') OR
(m.meta_key != 'gtp_product_dont_show')
...
Just a side note, I don't recommend storing booleans as strings like that. You should consider using a TINYINT() where boolean fields are stored as 0 for false, or 1 for true.

Bespoke SQL query - accessing records based on 2 (or more) postmeta fields

I'm running a site on Wordpress and I'm trying to get information from the postmeta table based on 2 (or more) fields. Here is my query so far:
SELECT wp_postmeta.* FROM wp_postmeta
LEFT JOIN wp_posts ON wp_posts.ID = wp_postmeta.post_id
WHERE wp_posts.post_status = 'publish'
AND wp_posts.post_type = 'post'
AND ( wp_postmeta.meta_key = 'relevantLine' AND wp_postmeta.meta_value = '339' )
AND (
( wp_postmeta.meta_key = 'brandOne' AND wp_postmeta.meta_value = '30' )
OR ( wp_postmeta.meta_key = 'brandTwo' AND wp_postmeta.meta_value = '30' )
OR ( wp_postmeta.meta_key = 'brandThree' AND wp_postmeta.meta_value = '30' )
)
AND wp_posts.post_date >= '2014-03-25'
AND wp_posts.post_date <= '2014-11-27'
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC
I'm trying to access the records that have the postmeta key "relevantLine" set to 339 AND the postmeta key "brandOne" set to 30 (or "brandTwo" set to 30, or "brandThree" set to 30).
Does anyone have any idea how to do this?
The above query isn't working.
Many thanks
PS. I know I could use the wp query functionality but I would like to run the query this way if possible.
You can rewrite your as below
SELECT m.* ,m1.*
FROM wp_postmeta m
JOIN wp_posts p ON p.ID = m.post_id
JOIN wp_postmeta m1 ON p.ID = m1.post_id
WHERE p.post_status = 'publish'
AND p.post_type = 'post'
AND m.meta_key = 'relevantLine' AND m.meta_value = '339'
AND m1.meta_key IN ('brandOne','brandThree','brandTwo')
AND m1.meta_value = '30'
AND p.post_date >= '2014-03-25'
AND p.post_date <= '2014-11-27'
GROUP BY p.ID
ORDER BY p.post_date DESC
This structure is call EAV entity attribute value and for matching between different keys you have to join the table as the different keys you want to compare,I have added only one join to wp_postmeta and for the keys of single value that is 30 i have used IN() to simplify your query.
Note Using GROUP BY without any aggregate function will give you
indeterminate results

Woocommerce query for pending orderd

I want a mysql query to get all my orderd on pending status. Somebody know how to do that.
I'm using woocommerce ina wordpress website, but I just want the mysql query not with wordpress functions.
Thanks
You really should use the built-in database functions since that complies with the Wordpress coding standards.
You could look at the WC_Query class.
Or you could try something like the below. You will need to change the meta key to whatever the meta key is they are using. Also the meta value might be different than pending and the post_type may be different than 'shop_order'.
$pending = new WP_Query(
array(
'post_type' => array('shop_order'),
'meta_query' => array(
array(
'key' => 'status',
'value' => array('pending'),
)
)
)
);
Here is one example on how to do a meta query of woocommerce orders.
OK guys, it is a weird issue, but I fixed it by simply using a custom query. Somehow adding 'post_status' => 'wc-pending' doesn't actually change the query, but if I use pending, the query changes.
So what I did was using that custom query and modify pending to wc-pending.
Well I spent the weekend working on the query and here is the result:
select
nombre,apellido,direccion,direccion2,codigo,poblacion,provincia,correo, telefono
from (
select
(select meta_value from wp_postmeta pm1 where p.ID = pm1.post_id and meta_key = "_billing_first_name") as nombre,
(select meta_value from wp_postmeta pm1 where p.ID = pm1.post_id and meta_key = "_billing_last_name") as apellido,
(select meta_value from wp_postmeta pm1 where p.ID = pm1.post_id and meta_key = "_billing_address_1") as direccion,
(select meta_value from wp_postmeta pm1 where p.ID = pm1.post_id and meta_key = "_billing_address_2") as direccion2,
(select meta_value from wp_postmeta pm1 where p.ID = pm1.post_id and meta_key = "_customer_user") as codigo,
(select meta_value from wp_postmeta pm1 where p.ID = pm1.post_id and meta_key = "_billing_city") as poblacion,
(select meta_value from wp_postmeta pm1 where p.ID = pm1.post_id and meta_key = "_billing_state") as provincia,
(select meta_value from wp_postmeta pm1 where p.ID = pm1.post_id and meta_key = "_billing_email") as correo,
(select meta_value from wp_postmeta pm1 where p.ID = pm1.post_id and meta_key = "_billing_phone") as telefono
from
wp_posts AS p
WHERE post_type = "shop_order" and id in (SELECT object_id
FROM wp_posts
LEFT OUTER JOIN wp_term_relationships ON wp_posts.ID=wp_term_relationships.object_id
WHERE post_type = "shop_order"
AND term_taxonomy_id=9
)
) A

Retrieve wordpress posts with featured image via SQL

I'm using this query in a PHP script outside Wordpress to retrieve entries with their featured images
SELECT ( SELECT guid FROM wp_posts WHERE id = m.meta_value ) AS url
FROM wp_posts p, wp_postmeta m
WHERE p.post_type = 'post'
AND p.post_status = 'publish'
AND p.id = m.post_id
AND m.meta_key = '_thumbnail_id'
...and it works fine.
But this way I get full-size image URL. I need to retrieve 'medium' or 'thumbnail' sizes of these images.
¿Any way to achieve this?
here is the response :
SELECT TITRE,DESCR,URL, CONCAT(LEFT(IMG, LENGTH(IMG) - LOCATE('.',
REVERSE(IMG))),'-150x150.',SUBSTRING_INDEX(IMG, '.', -1)) AS IMG FROM (
SELECT
p.`post_title` AS TITRE,
(SELECT `meta_value` FROM wp_postmeta WHERE `post_id` = p.`ID` and `meta_key`='_yoast_wpseo_metadesc') AS DESCR,
p.`guid` AS URL,
(SELECT `guid` FROM wp_posts WHERE id = m.meta_value) AS IMG
FROM wp_posts p, wp_postmeta m
WHERE p.post_type = 'post'
AND p.post_status = 'publish'
AND p.id = m.post_id
AND m.meta_key = '_thumbnail_id') TT
where DESCR is not null
The following query, adapted from the above, solved my particular problem which was simply to grab the last four posts and their featured images. Plus the post_name from which I could construct a pretty URL
SELECT title, post_name, date, content, CONCAT(LEFT(image, LENGTH(image) - LOCATE('.', REVERSE(image))),'-150x150.',SUBSTRING_INDEX(image, '.', -1)) AS image
FROM (
SELECT
p.post_title AS title,
p.post_status AS 'status',
p.post_date AS date,
p.post_content AS content,
p.post_name AS post_name,
(SELECT `guid` FROM wp_posts WHERE id = m.meta_value) AS image
FROM wp_posts p, wp_postmeta m
WHERE p.post_type = 'post'
AND p.post_status = 'publish'
AND p.id = m.post_id
AND m.meta_key = '_thumbnail_id'
ORDER BY date DESC
LIMIT 4
) TT
Of course from there it's easy to make an excerpt etc using:
for($i=0; $i< $num_rows; $i++){
$post_content = mysql_result($query_result, $i, "content");
$post_excerpt = substr($post_content, 0, 90);
$post_permalink = $post_url . mysql_result($query_result, $i, "post_name");
echo $post_permalink; //etc
}
You can try this query for thumbnail size , for medium image i am not sure about the right size if you know the dimension then make custom alias as i made below using the SUBSTRING_INDEX to get the extension of file then i have used CONCAT function with the post_name column and the dimensions + extension ,similarly you can do this for medium size , As all upload goes to the upload folder you can analyze the generated thumbs name are original attachment name + -150x150 or other dimensions so from this logic your thumbs get the name with the dimensions, the attachments of post are stored in post_meta with the post id and having key name _wp_attachment_metadata which stores all the information about different sizes of file but in a serialized form so in mysql query you cannot unserialize the data
SELECT
CONCAT(p.`post_name` ,'-150x150.',
SUBSTRING_INDEX(( SELECT `guid` FROM wp_posts WHERE id = m.meta_value ), '.', -1) )
AS `thumbnail`,
(SELECT guid FROM wp_posts WHERE id = m.meta_value ) AS `full`
FROM wp_posts p, wp_postmeta m
WHERE p.post_type = 'post'
AND p.post_status = 'publish'
AND p.id = m.post_id
AND m.meta_key = '_thumbnail_id'
This query works for me to get thumbnail of size 150*150 hope it works for you also
SELECT
p.ID,
p.post_title AS title,
p.post_name AS post_name,
(SELECT meta_value from wp_postmeta where post_id = m.meta_value and meta_key='_wp_attachment_metadata') AS meta_value
FROM
wp_posts p,
wp_postmeta m
WHERE
p.post_type = 'post'
AND p.post_status = 'publish'
AND p.id = m.post_id
AND m.meta_key = '_thumbnail_id'
ORDER BY
p.post_date DESC
LIMIT 5;
And then use unserialize PHP function with meta_value

Categories