I need help in rewriting the query below to accept a second and a second + third qualification.
Example meta keys and values:
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
I attempted to add these AND statements but I was not able to cause it to work properly.
Second qualification:
AND (pm.meta_key = 'states' AND pm.meta_value = 'california')
Second and third qualification:
AND (pm.meta_key = 'states' AND pm.meta_value = 'california')
AND (pm.meta_key = 'countires' AND pm.meta_value = 'usa')
Function with query I need help in rewritting:
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;
}
Thanks in advance for your help! Please let me know if further clarification is required.
If the function sets $key=trees, what is the point of an empty check? Additionally, I think you are missing the curly brackets. You are selecting 'pm.meta_value', which is why are you doing a LEFT JOIN, I think? Maybe seeing your DB structure would help me understand that, but an INNER JOIN is what you want.
if( empty( $key ) ){
return;
} else {
$res = $wpdb->get_col( $wpdb->prepare( "
SELECT DISTINCT pm.meta_value FROM {$wpdb->postmeta} pm
INNER JOIN {$wpdb->posts} as 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;
}
Try this. If it doesn't work then update this question with more details and I will help guide you further.
Related
I'm trying to show the total value for all orders in certain status whose payment method is "ppec-paypal".
I've tried using the AND function to filter by meta.meta_value
add_shortcode( 'show_total_pp', 'show_total_pp_shortcode' );
function show_total_pp_shortcode() {
global $wpdb;
$order_totalpp = apply_filters( 'woocommerce_reports_sales_overview_order_totals', $wpdb->get_row( "
SELECT SUM(meta.meta_value) AS total_sales, COUNT(posts.ID) AS total_orders FROM {$wpdb->posts} AS posts
LEFT JOIN {$wpdb->postmeta} AS meta ON posts.ID = meta.post_id
WHERE meta.meta_key = '_order_total'
AND posts.post_type = 'shop_order'
AND meta.meta_value = 'ppec_paypal'
AND posts.post_status IN ( '" . implode( "','", array( 'wc-processing','wc-on-hold' ) ) . "' )
" ) );
return absint( $order_totalpp->total_sales);
echo $order_totalpp;
}
I have this code string working for orders based on just the status's, but when I try to filter the payment method by adding the line:
" AND meta.meta_value _payment_method = 'ppec_paypal' "
it does not work, gets a '0' value.
I'm guessing there is syntax error in my code.
for a left join you should not use column related to the left joined table in where clause (this way work as an inner join)
but you should add this condition to the related ON clause
SELECT SUM(meta.meta_value) AS total_sales, COUNT(posts.ID) AS total_orders
FROM {$wpdb->posts} AS posts
LEFT JOIN {$wpdb->postmeta} AS meta ON posts.ID = meta.post_id
AND meta.meta_key = '_order_total'
AND meta.meta_value = 'ppec_paypal'
WHERE posts.post_type = 'shop_order'
AND posts.post_status IN ( '" . implode( "','", array( 'wc-processing','wc-on-hold' ) ) . "' )
I try to get the post_ids from postmeta where the _sale_price_dates_to are less the now. And I did something like this:
global $wpdb;
$publishid = $wpdb->get_results('SELECT meta_value FROM ' . $wpdb->postmeta . ' WHERE meta_key="_sale_price_dates_to" and meta_value<=' .time().'') or die("Error: Cannot create object");
But it doesn't work. Maybe because the _sale_price_dates_to has format longtext not date. how to change it in the query?
But It's not over. I want to add the condition that the products have to be published then I have to join:
$publishid = $wpdb->get_results('SELECT meta_value FROM ' . $wpdb->postmeta . 'join' . $wpdb->posts . ' ON wp_posts.ID = wp_postmeta.post_id WHERE wp_postmeta.meta_key="_sale_price_dates_to" and wp_postmeta.meta_value<=' .time().' and wp_posts.post_status="publish" ') or die("Error: Cannot create object");
But because of the first problem, I don't know it works.
Update: Setting up the right time zone in the code
Try the following to make a functional SQL query using WPDB to get the Post IDs where post meta _sale_price_dates_to timestamp is less the now time stamp:
global $wpdb;
// Set the correct time zone (http://php.net/manual/en/timezones.php)
date_default_timezone_set('Europe/Paris');
// An array of IDs
$results = $wpdb->get_col("
SELECT p.ID
FROM {$wpdb->prefix}posts AS p
JOIN {$wpdb->prefix}postmeta AS pm ON p.ID = pm.post_id
WHERE p.post_status = 'publish'
AND pm.meta_key = '_sale_price_dates_to'
AND pm.meta_value <= '".time()."'
AND pm.meta_value != ''
");
// Raw Output (array of post IDs)
print_r($results);
Tested and works.
meta_value != '' is needed to avoid Post IDs with empty values to be queried.
I'm trying to sum specific items for each user, but it seems it doesn't recognize the current user and it sums all the orders for all customers.
How can I solve this? What I am missing?
Here's the code I am using:
$order_items = apply_filters( 'woocommerce_reports_top_earners_order_items', $wpdb->get_results( "
SELECT order_item_meta_2.meta_value as product_id, SUM( order_item_meta.meta_value ) as line_total FROM {$wpdb->prefix}woocommerce_order_items as order_items
LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta as order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id
LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta as order_item_meta_2 ON order_items.order_item_id = order_item_meta_2.order_item_id
LEFT JOIN {$wpdb->posts} AS posts ON order_items.order_id = posts.ID
WHERE posts.post_type = 'shop_order'
AND posts.post_status IN ( '" . implode( "','", array( 'wc-completed', 'wc-processing', 'wc-on-hold' ) ) . "' )
AND order_items.order_item_type = 'line_item'
AND order_item_meta.meta_key = '_line_total'
AND order_item_meta_2.meta_key = '_product_id'
GROUP BY order_item_meta_2.meta_value
" ));
$totalPR = 0;
$Products = array(1507, 1406, 1506);
foreach ($order_items as $item) {
if (in_array($item->product_id, $Products)) {
$totalPR = $item->line_total + $totalPR;
echo $totalPR;
}
}
Update 2 - It's working making this:
Get the list of the customers
Go through each customer in a foreach loop
Get the customer ID
Add a LEFT JOIN for wp_postmeta table on the post_id:
LEFT JOIN {$wpdb->postmeta} AS postmeta ON order_items.order_id = postmeta.post_id
insert this 2 lines into your WHERE:
AND postmeta.meta_key = '_customer_user'
AND postmeta.meta_value = '$customer_id'
Then comes your loop inside the customers loop, to get the sum by customer
This is the code:
global $wpdb;
// Set here your product ids
$products = array( 1507, 1406, 1506 );
$all_customers = get_users( 'role=customer' );
foreach ( $all_customers as $customer ) {
$customer_id = $customer->ID;
$total_pr = 0;
$query = $wpdb->get_results("
SELECT order_item_meta_2.meta_value as product_id,
SUM( order_item_meta.meta_value ) as line_total
FROM {$wpdb->prefix}woocommerce_order_items as order_items
LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta as order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id
LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta as order_item_meta_2 ON order_items.order_item_id = order_item_meta_2.order_item_id
LEFT JOIN {$wpdb->postmeta} AS postmeta ON order_items.order_id = postmeta.post_id
LEFT JOIN {$wpdb->posts} AS posts ON order_items.order_id = posts.ID
WHERE posts.post_type = 'shop_order'
AND posts.post_status IN ( '" . implode( "','", array( 'wc-completed', 'wc-processing', 'wc-on-hold' ) ) . "' )
AND postmeta.meta_key = '_customer_user'
AND postmeta.meta_value = '$customer_id'
AND order_items.order_item_type = 'line_item'
AND order_item_meta.meta_key = '_line_total'
AND order_item_meta_2.meta_key = '_product_id'
GROUP BY order_item_meta_2.meta_value
");
$results = apply_filters( 'woocommerce_reports_top_earners_order_items', $query );
foreach ( $results as $values ) {
if ( in_array( $values->product_id, $products ) ) {
$total_pr += $values->line_total;
}
}
echo 'customer ID: ' . $customer->ID . ' | Total PR: ' . number_format( $total_pr, 2 ) . '<br>';
}
Tested and works. It will output the list with the Customer IDs and the corresponding Total PR.
References:
WordPress Code Reference - get_users()
php variable in sql query
$current_user = wp_get_current_user();
$current_user_id = $current_user->ID;
$args = array(
'customer_id' => $current_user_id
);
$orders = wc_get_orders($args);
You Can Use wp_get_current_user(); for Get Current User And Get Order Data With Args May be It's Work For You.$current_user_id = $current_user->ID;echo $current_user_id;//check current user id get or notecho $current_user_id;//check current user id get or not
Im trying to filter my next_post_link and previous_post_link so it can be used on a custom post type called filmfremvisning with a meta_key field with a date in it. The filmfremvisning CPT is some kind of "events" CPT where the event posts have an expiration date on them. The expiration date has the following format of YYYYMMDD and is named dato_for_fremvisningen.
I also have a custom post status called expired and a cronjob that gives all expired posts that status every night.
I have tried these two links:
https://wordpress.stackexchange.com/questions/139453/filter-next-post-link-and-previous-post-link-by-meta-key
http://return-true.com/2012/04/custom-ordering-for-wordpress-post-link-functions/
And I got it working quite nice. The problem however is that the INNER JOIN is skipping posts that has the same date.
For example if I have the following posts and dates:
Event 1 - 20140102
Event 2 - 20140105
Event 3 - 20140105
Event 4 - 20140107
It returns:
Event 1 - 20140102
Event 2 - 20140105
Event 4 - 20140107
The SQL statement is for furture post is:
INNER JOIN $wpdb->postmeta AS m ON p.ID = m.post_id
WHERE p.post_type = 'filmfremvisning'
AND p.post_status = 'publish'
AND m.meta_key = 'dato_for_fremvisningen'
AND m.meta_value > '$current_filmfremvisning_date'
GROUP BY p.ID ORDER BY m.meta_value ASC`
The code im using in functions.php is down below:
function get_adjacent_past_events_join($join) {
if(is_singular('filmfremvisning')) {
global $wpdb;
$new_join = $join."INNER JOIN $wpdb->postmeta AS m ON p.ID = m.post_id ";
return $new_join;
}
return $join;
}
add_filter('get_previous_post_join', 'get_adjacent_past_events_join');
add_filter('get_next_post_join', 'get_adjacent_past_events_join');
function get_future_filmfremvisnings_where($where) {
if(is_singular('filmfremvisning')) {
global $wpdb, $post;
$id = $post->ID;
$current_filmfremvisning_date = get_field('dato_for_fremvisningen', $id);
$new_where = "WHERE p.post_type = 'filmfremvisning' AND p.post_status = 'publish' AND m.meta_key = 'dato_for_fremvisningen' AND m.meta_value > '$current_filmfremvisning_date'";
return $new_where;
}
return $where;
}
add_filter('get_next_post_where', 'get_future_filmfremvisnings_where');
function get_past_filmfremvisnings_where($where) {
if(is_singular('filmfremvisning')) {
global $wpdb, $post;
$id = $post->ID;
$current_filmfremvisning_date = get_field('dato_for_fremvisningen', $id);
$new_where = "WHERE p.post_type = 'filmfremvisning' AND p.post_status = 'publish' AND m.meta_key = 'dato_for_fremvisningen' AND m.meta_value < '$current_filmfremvisning_date'";
return $new_where;
}
return $where;
}
add_filter('get_previous_post_where', 'get_past_filmfremvisnings_where');
function get_prev_past_filmfremvisnings_sort($sort) {
if(is_singular('filmfremvisning')) {
global $wpdb;
$new_sort = " GROUP BY p.ID ORDER BY m.meta_value DESC";
return $new_sort;
}
return $sort;
}
add_filter('get_previous_post_sort', 'get_prev_past_filmfremvisnings_sort');
function get_next_future_filmfremvisnings_sort($sort) {
if(is_singular('filmfremvisning')) {
global $wpdb;
$new_sort = " GROUP BY p.ID ORDER BY m.meta_value ASC";
return $new_sort;
}
return $sort;
}
add_filter('get_next_post_sort', 'get_next_future_filmfremvisnings_sort');
I am running a competition which is based on WP Custom Fields. I am trying to count all meta values of a meta_key='odd' for a specific user. I am using the formula below but it's not returning any result.
$meta_key = 'odd';
$post_author = 'Admin';
$odd = $wpdb->get_var( $wpdb->prepare(
"
SELECT Count(meta_value)
FROM $wpdb->postmeta
INNER JOIN $wpdb->posts ON $wpdb->postmeta->post_id = $wpdb->posts->ID
WHERE $wpdb->postmeta->meta_key = 'odd' AND $wpdb->posts->post_author = 'Admin'
",
$meta_key, $post_author
) );
echo "<p>Total odd {$odd}</p>";
Anyone can help me? Thanks in advance.
You are mixing up the $wpdb variables and the $post variables - for your JOIN, for example, you can't use $wpdb->postmeta->post_id, it would be {$wpdb->postmeta}.post_id, and would be even better to just use table aliases. Your prepare() is also not passing in your meta_key or author because you don't have %s placeholders for them
$odd = $wpdb->get_var( $wpdb->prepare(
"
SELECT count(meta_value)
FROM {$wpdb->postmeta} pm
INNER JOIN {$wpdb->posts} p ON pm.post_id = p.ID
WHERE pm.meta_key = %s AND p.post_author = %s
",
$meta_key, $post_author
) );