Wordpress SQL statement to exclude certain category - mysql

I am wondering how I can rework this statement to exclude a certain category, ie. category id = 14
Please note that the wordpress categories are in a different table.
referenced as term_relationships and the category is term_taxonomy_id
<?php
$now = gmdate("Y-m-d H:i:s", strtotime('0 days'));
$request = $wpdb->prepare("SELECT ID, post_title, post_date, post_excerpt,LEFT(post_content,$sqllimit) AS short_post_content FROM $wpdb->posts WHERE post_status = 'publish' ");
if($hide_pass_post) $request .= "AND post_password ='' ";
if($include_pages) $request .= "AND (post_type='post' OR post_type='
else $request .= "AND post_type='post' ";
$request .= "AND post_date_gmt > '$now' ORDER BY post_date ASC LIMIT $skip_posts, $returnnum";
$posts = $wpdb->get_results($request); ?>

$request = $wpdb->prepare("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->term_taxonomy.term_id = 3
AND $wpdb->term_taxonomy.term_id <> 14
AND $wpdb->term_taxonomy.taxonomy = 'category'
AND $wpdb->posts.post_type = 'post'
AND $wpdb->posts.post_status = 'publish')");

Related

How do I combine 2 SELECT statements where the result

How do I combine 2 SELECT statements where the result of the first select is used in the WHERE of the second SELECT
Below is the code I am using right now:
$order_id = 7655;
$first = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM wp_postmeta WHERE meta_key = '_ticket_order' AND meta_value = %d", $order_id ) );
if ( $first ) {
$second = $wpdb->get_var( $wpdb->prepare( "SELECT meta_value FROM wp_postmeta WHERE meta_key = '_ticket_event' AND post_id = %d", $first ) );
}
echo $second;
You could try using a join between the two queries
$second = $wpdb->get_var( $wpdb->prepare("SELECT b.meta_value
FROM wp_postmeta a
INNER JOIN wp_postmeta b ON a.post_id = b.post_id
WHERE a.meta_key = '_ticket_order' AND a.meta_value = %d", $order_id ) );

Why does $wpdb->get_result() return value different from the get_posts() from add_filter()

I'm new to Wordpress programming, I want to make a custom code, the problem here is:
I got the different values from almost identical sql queries. The first one from $wpdb->get_results() function and the another one from the add_filter() function.
So why I would do this? it's because I have a database, where the items have different currency. So I would like to sort the price after change it to the default currency which is USD in my case. (I already have the function tho), so the problem is I don't get the same post ID even though it's already similar
Here is the query I wrote on $wpdb
$results = $wpdb->get_results("
SELECT
wp_posts.ID AS id,
price.meta_value AS price_value,
currency.meta_value AS currency_value
FROM
wp_posts
INNER JOIN " . $wpdb->postmeta . " ON (" . $wpdb->posts . ".ID = wp_postmeta.post_id)
INNER JOIN " . $wpdb->postmeta . " AS currency ON (" . $wpdb->posts . ".ID = currency.post_id AND currency.meta_key = 'month_currency')
INNER JOIN " . $wpdb->postmeta . " AS price ON (" . $wpdb->posts . ".ID = price.post_id AND price.meta_key = 'month_price')
WHERE
1=1
AND ((wp_postmeta.meta_key = 'monthly' AND wp_postmeta.meta_value = 'Y'))
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')
GROUP BY
wp_posts.ID
LIMIT
0, 12
");
And the result is:
ID: 40168
ID: 39832
ID: 40346
ID: 40846
ID: 42200
ID: 39687
ID: 39467
ID: 29605
ID: 32620
ID: 32773
ID: 35175
ID: 17
There are a lot of code here between them
And this one is from the add_filter function:
$mam_global_fields = ', price.meta_value';
$mam_global_join = "
INNER JOIN " . $wpdb->postmeta . " AS currency ON (" . $wpdb->posts . ".ID = currency.post_id AND cur.meta_key = 'month_currency')
INNER JOIN " . $wpdb->postmeta . " AS price ON (" . $wpdb->posts . ".ID = price.post_id AND price.meta_key = 'month_price')";
$mam_global_orderby = "FIELD(" . $wpdb->posts . ".ID" . $order_id . ")";
And here is the query that created by the add_filter()
SELECT
SQL_CALC_FOUND_ROWS DISTINCT wp_posts.*,
price.meta_value
FROM
wp_posts
INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id)
INNER JOIN wp_postmeta AS currency ON (wp_posts.ID = currency.post_id AND currency.meta_key = 'month_currency')
INNER JOIN wp_postmeta AS price ON (wp_posts.ID = price.post_id AND price.meta_key = 'month_price')
WHERE
1=1
AND ((wp_postmeta.meta_key = 'monthly' AND wp_postmeta.meta_value = 'Y'))
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')
GROUP BY
wp_posts.ID
ORDER BY
FIELD(wp_posts.ID, 40168, 39832, 40346, 40846, 42200, 39687, 39467, 29605, 32620, 32773, 35175, 17)
LIMIT
0, 12
The ID order already correct but the query showing another post which is not the exact ID value like the $wpdb, so why it's happened?
Or is there any better way that I can use instead this one? I appreciate any kind of help, thank you

Wordpress search result postmeta and term

What´s the problem with this?
I´m trying to search in wp_postmeta and wp_terms but i getting just one or another, never both. I already tried change OR to AND in WHERE, but nothing happens and no result is printed.
Thanks!
$join .= "
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
INNER JOIN $wpdb->term_taxonomy ON $wpdb->term_taxonomy.term_taxonomy_id = $wpdb->term_relationships.term_taxonomy_id
INNER JOIN $wpdb->terms ON $wpdb->terms.term_id = $wpdb->term_taxonomy.term_id
";
and this...
$where .= "
OR ( $wpdb->postmeta.meta_value LIKE '%".get_search_query()."%' AND $wpdb->posts.post_status = 'publish' )
OR ( $wpdb->terms.name LIKE '%".get_search_query()."%' AND $wpdb->posts.post_status = 'publish' )
";
UPDATE 1
After reading here https://support.advancedcustomfields.com/forums/topic/mistake-in-documentation-query-posts-by-custom-fields/ — I´ve changed the two "inner join" for "join" and it worked fine. I don´t know exactly why it works. But unfortunately still very slow to get the results.
Could you tell me if this is the best approach for what I'm looking for?
add_filter( 'posts_join', 'custom_search_join' );
add_filter( 'posts_where', 'custom_search_where' );
add_filter( 'posts_distinct', 'custom_search_distinct' );
function custom_search_join( $join ) {
global $wpdb;
if( !is_admin() ) {
if( is_search() ) {
$join .= "
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_taxonomy.term_taxonomy_id = $wpdb->term_relationships.term_taxonomy_id
LEFT JOIN $wpdb->terms ON $wpdb->terms.term_id = $wpdb->term_taxonomy.term_id
";
print_r( $join ) ;
}
}
return $join;
}
function custom_search_where( $where ) {
global $wpdb;
if( !is_admin() ) {
if( is_search() ) {
$where .= "
OR ( $wpdb->postmeta.meta_value LIKE '%".get_search_query()."%' )
OR ( $wpdb->terms.name LIKE '%".get_search_query()."%' )
AND $wpdb->posts.post_status = 'publish'
";
print_r( $where ) ;
}
}
return $where;
}
function custom_search_distinct( $where ) {
global $wpdb;
if( !is_admin() ) {
if( is_search() ) {
return "DISTINCT";
}
}
return $where;
}
UPDATE 2
After some research and study.
Define list of ACF fields that will be searched
Define taxonomies to be searched
Running fast so far.
If anyone knows of a way to improve this code I really appreciate it.
add_filter( 'posts_search', 'busca_acf', 500, 2 );
function lista_campos_acf() {
$lista_campos_acf = [ 'acf-field-example' ];
return $lista_campos_acf;
}
function lista_taxonomias() {
$lista_taxonomias = [ 'post_tag', 'category', 'example_taxonomy' ];
return $lista_taxonomias;
}
function busca_acf( $where, $wp_query ) {
if( !is_admin() ) {
global $wpdb;
$termos = remove_accents( $wp_query->query_vars[ 's' ] );
$exploded = array_map( 'strtolower', explode( ' ', $termos ) );
$lista_campos_acf = lista_campos_acf();
$lista_taxonomias = lista_taxonomias();
$where = '';
foreach( $exploded as $tag ) {
$where .= "
AND (
( wp_posts.post_title LIKE '%$tag%' )
OR ( wp_posts.post_content LIKE '%$tag%' )
OR EXISTS (
SELECT *
FROM wp_postmeta
WHERE post_id = wp_posts.ID
AND ( ";
foreach( $lista_campos_acf as $campo_acf ) {
if( $campo_acf == $lista_campos_acf[0] ) {
$where .= " ( meta_key LIKE '%" . $campo_acf . "%' AND meta_value LIKE '%$tag%' ) ";
}
else {
$where .= " OR ( meta_key LIKE '%" . $campo_acf . "%' AND meta_value LIKE '%$tag%' ) ";
}
}
$where .= ")
)
OR EXISTS (
SELECT *
FROM wp_terms
INNER JOIN wp_term_taxonomy ON wp_term_taxonomy.term_id = wp_terms.term_id
INNER JOIN wp_term_relationships ON wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id
WHERE ( ";
foreach ( $lista_taxonomias as $tax ) {
if( $tax == $lista_taxonomias[0] ) {
$where .= "taxonomy = '" . $tax . "'";
}
else {
$where .= "OR taxonomy = '" . $tax . "'";
}
}
$where .= ")
AND object_id = wp_posts.ID
AND wp_terms.name LIKE '%$tag%'
)
)
";
}
return $where;
}
}

mysql additional condition after INNER JOIN, ON

I have this query right now
global $wpdb;
$interval = "1 WEEK";
$now = current_time('mysql');
$top4=$wpdb->get_results('SELECT ID, post_title, post_name from `'.$wpdb->prefix.'popularpostssummary`
INNER JOIN `'.$wpdb->prefix.'posts` ON `postid`=`ID`
ORDER BY `pageviews` DESC
LIMIT 4;', ARRAY_A);
And I want to add the following conditions, what's the proper way of adding them in the code?
WHERE post_type = post
AND last_viewed > DATE_SUB('{$now}', INTERVAL {$interval})
post_type is under '.$wpdb->prefix.'posts
while last_viewed is under '.$wpdb->prefix.'popularpostssummary
global $wpdb;
$interval = "1 WEEK";
$now = current_time('mysql');
$sql =
'SELECT p.ID, p.post_title, p.post_name
FROM `' . $wpdb->prefix . 'popularpostssummary` AS pps
INNER JOIN `' . $wpdb->prefix . 'posts` AS p ON pps.`postid`= p.`ID`
WHERE p.post_type = "post"
AND pps.last_viewed > DATE_SUB("' . $now . '", INTERVAL ' . $interval . ')
ORDER BY pps.`pageviews` DESC
LIMIT 4;';
echo $sql; exit;
$top4 = $wpdb->get_results( $sql, ARRAY_A );

wordpress query_posts to look at meta info

I am looking to run a query with query_posts that lets me look at meta_fields.
I have done this once before and achieved the result I wanted but now for some reason adding an extra field into the equation returns nothing.
The query below returns all attachments where the lottery_year is equal to $y, and obviously $y can be 2011 or earlier.
Now my next step I want to bring in another meta_field called photo_technique and give that one a value.
Question, how do I do that?
$querystr = "
SELECT $wpdb->posts.*
FROM $wpdb->posts
LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id)
WHERE ($wpdb->postmeta.meta_key = 'lottery_year' AND $wpdb->postmeta.meta_value = $y)
AND $wpdb->posts.post_type = 'attachment'
ORDER BY $wpdb->postmeta.meta_value ASC
LIMIT 100
";
If you whant to display posts that have either lottery_year = $y ( or ) photo_technique = $x, you could use :
$querystr = "
SELECT $wpdb->posts.*
FROM $wpdb->posts
LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id)
WHERE ($wpdb->postmeta.meta_key = 'lottery_year' AND $wpdb->postmeta.meta_value = $y) OR ($wpdb->postmeta.meta_key = 'photo_technique' AND $wpdb->postmeta.meta_value = $x)
AND $wpdb->posts.post_type = 'attachment'
ORDER BY $wpdb->postmeta.meta_value ASC
LIMIT 100
";
Edit
If you whant to display results that have both lottery_year = $y ( AND ) photo_technique = $x, you could use the following query :
$querystr = "
SELECT
$wpdb->posts.*
FROM
$wpdb->posts
INNER JOIN $wpdb->postmeta ON
$wpdb->posts.ID = $wpdb->postmeta.post_id
AND $wpdb->postmeta.meta_key IN ( 'lottery_year', 'photo_technique' )
AND $wpdb->postmeta.meta_value IN ( '$y', '$x' )
WHERE $wpdb->posts.post_type = 'attachment'
GROUP BY $wpdb->posts.ID
HAVING COUNT(1) = 2
ORDER BY $wpdb->postmeta.meta_value ASC
LIMIT 100
";
Edit
The last query ( the AND one ) will fail in some circumstances. For example you whant
lottery_year = $y AND photo_technique = $x, but it will allso return results that have the $x and $y switched like : lottery_year = $x AND photo_technique = $y, it realy depends when you can rely on it or not, like do you have a photo_technique that is called for example '2001' ( witch could pass as a lottery_year too ) . Please be carefull with it or ask this question on dba.stackexchange.com or wordpress.stackexchange.com .