Custom SQL query with custom taxonomies (Wordpress) - php

I use the following SQL query to fetch custom posts in Wordpress.
I ended up with this solution because i needed to fetch und sort the posts based on custom meta data. This woks pretty well so far!
But how do i incorporate custom taxonomies in my query?
Say for example only fetch posts that are associated with term_id 5?
I'm really stuck here cause i can't figure out how wp_terms, relations etc are connected...
Any help is greatly appreciated!
UPDATE:
After some reading the solution in my case is this:
WordPress stores the relations between taxonomies and posts in wp_term_relationships (where object_id is the post_id and term_taxonomy_id ist the term_id in wp_terms). So if i want to only fetch posts that belong to a specific term_id, i came up with the following query. Seems to work as far as i can tell!
This is my query
global $wpdb;
$activelang = ICL_LANGUAGE_CODE;
$cmonth = date('Y-m');
$myquery = "
SELECT wposts.*, wpostmeta.meta_value AS date
FROM wp_posts wposts, wp_postmeta wpostmeta, wp_icl_translations wicl_translations, , wp_term_relationships wptermrelations
WHERE wposts.post_status = 'publish'
AND wpostmeta.post_id = wposts.ID
AND (wptermrelations.object_id = wposts.ID AND (wptermrelations.term_taxonomy_id = '29' OR wptermrelations.term_taxonomy_id = '30'))
AND wposts.post_type = 'event'
AND wicl_translations.element_id = wposts.ID
AND wicl_translations.language_code = '$activelang'
AND (wpostmeta.meta_key = '_ws_prem_date' OR wpostmeta.meta_key = '_ws_date1_date' OR ... ... OR wpostmeta.meta_key = '_ws_date10_date')
AND wpostmeta.meta_value >= '$cmonth-01'
ORDER BY CAST(date AS DATETIME),wposts.post_title ASC
";
$myloop = $wpdb->get_results($myquery);
In case someone is wondering what this query does:
This query fetches custom post types (events that have multiple dates associated) and builds a loop for these events that allows for duplicate entries since a 'normal' WordPress loop always filters out any duplicate entries.

Related

SQL Fetching Woocommerce Product Thumbnail From DB

I've been searching through the past two days to find out where exactly could the Woocommerce products thumbnails (images) texts and URL's are stored inside the database tables, but still cannot figure this out!
I'm in a situation where I must use SQL queries to move the products data into another tables, and I have to implement the process from my phpmyadmin panel.
I already searched the wp_posts and wp_postmeta tables, wp_posts contains a guide column for the url to the product which post_type like 'product%', So far I know that in general the post stores it's thumbnalis link inside one of the posts with a type of attachment , while I need the posts with a post_type of product or like so.
Hope I can find some answers here, Thanks.
You can use the Wordpress WP_Query to get the thumbnail image of product.
$args = array(
'post_type' => 'product', //post type of product
'posts_per_page' => -1
);
$query= new WP_Query( $args );
while ( $query->have_posts() ) : $query->the_post();
global $product;
//woocommerce_get_product_thumbnail is use to get the product thumbnail link
echo '<br />' . woocommerce_get_product_thumbnail().' '.get_the_title().'';
endwhile;
wp_reset_query();
Solution 2- using the custom query as you mention in query.
//Using custom query get the details from wp_postmeta and wp_posts
//_wp_attached_file - meta key for image
$querystr = "SELECT p.*, pm2.meta_value as product_image FROM wp_posts p LEFT JOIN
wp_postmeta pm ON (
pm.post_id = p.id
AND pm.meta_value IS NOT NULL
AND pm.meta_key = '_thumbnail_id'
)
LEFT JOIN wp_postmeta pm2 ON (pm.meta_value = pm2.post_id AND pm2.meta_key = '_wp_attached_file'
AND pm2.meta_value IS NOT NULL) WHERE p.post_status='publish' AND p.post_type='product'
ORDER BY p.post_date DESC";
$upload_dir = wp_upload_dir();
//get wp_upload url
$wp_upload_url = $upload_dir['baseurl'];
$pageposts = $wpdb->get_results($querystr, OBJECT);
foreach ($pageposts as $post){
echo "<br /><a href='".$post->guid."'><img src='". $wp_upload_url.'/'.$post->product_image."'>".$post->post_title."</a>";
}

How can I cross-reference a database table by itself?

I've been trying to find a way (armed with only a basic knowledge of php and a wildly optimistic sense of determination) to search a wordpress database for meta-values based on other meta-values.
I need to get an item name from one table (wp_posts) using the post's ID, use it to obtain the post_id of items with the same name in another table (wp_postmeta) and then get from the same table the values for a particular custom field for every post_id obtained.
Since I'm new to this I attempted to do it by breaking it down into parts and here's what I've got.
<!-- This part works and gets the post title as expected -->
<?php
$result1 =$wpdb->get_results("SELECT post_title FROM $wpdb->posts , $wpdb->postmeta where $wpdb->posts.ID = $post->ID", OBJECT);
print_r($result1[0]->post_title);
?>
<!-- Then, I expected this to return the post_id of all entries where the title is the same as the one just obtained and where meta_key = custom_field_one. But it doesn't -->
<?php
$result2 =$wpdb->get_results("SELECT post_id FROM $wpdb->posts , $wpdb->postmeta where $wpdb->postmeta.meta_value = $result1 AND $wpdb->postmeta.meta_key = custom_field_one", OBJECT );
print_r($result2->post_id);
?>
<!-- So, unsurprisingly, this part doesn't work either. But it should use every post_id it just obtained to once again search the postmeta table -->
<?php
$result3 =$wpdb->get_results("SELECT meta_value FROM $wpdb->posts , $wpdb->postmeta where $wpdb->postmeta.post_id = $result2 AND $wpdb->postmeta.meta_key = custom_field_two", OBJECT );
print_r($result3->meta_value);
?>
Since the first query works, and the subsequent ones are just slight variations on that I expected it all to work. But, well, I was wrong.
Incidentally, I've tried a number of syntax variations in case that was an issue and I'm aware there are some issues regarding arrays. So any advice would be appreciated.
Use aliases:
SELECT
a1.Name,
b1.Info
FROM table2 b1
JOIN table2 a1 ON b1.id= a1.id AND a1.status = 1

Custom WP_Query order by post_meta and (author) user_meta

I am having an issue that i couldn't find on google and elsewhere.
To put problem in the context.
I am making a wordpress site where user can put their tutor listing for giving a tutorials, and i am implementing the system of evaluation of the tutors them self and their listening.
So I have tutor_listing post type and each tutor_listing has a 'post_score' meta value, and each tutor (user who puts his tutorials) has user_meta value called 'user_points'.
So I need a WP_Query that will get from the database all published tutor_listing but sorted by (post_score + user_points). Just to emphasis 'post_score' is a post_meta of the post_type tutor_listing and 'user_points' is user_meta of author of that post (tutor_listing).
Also i need that value to show in the loop.
I can get all the tutor_listing by
$args = array(
'post_type' => 'job_listing',
'post_status' => 'publish'
);
$query = new WP_Query( $args );
I can get the result from the custom wordpress sql query like this:
SELECT p1.ID, p1.post_author, p1.post_title, p1.post_date, (um1.meta_value + pm1.meta_value) AS total_score
FROM $wpdb->posts p1
JOIN $wpdb->users u1 ON (p1.post_author = u1.ID)
JOIN $wpdb->usermeta um1 ON (um1.user_id = u1.ID)
JOIN $wpdb->postmeta pm1 ON (pm1.post_id = p1.ID)
WHERE p1.post_type = 'tutor_listing'
AND p1.post_status = 'publish'
AND um1.meta_key = 'user_points'
AND pm1.meta_key = 'post_score'";
Can WP_Query provide such a functionality?
I need WP_Query to use its all extra functionality like pagination ect.
Or is there a way i could all the result done with the my custom sql give to WP_Query object?
Thank you

Search from all custom-fields very slow. I need filter search for custom post type

I'm doing a custom search in my WP and in the search field, any typed word will be sought in custom-fields, in the titles and posting content.
It turns out that my database has more than 1 million custom-fields lines, and wanted to limit the search only for a certain type of post.
I already do this in the Loop to display the results, but I wish this filter was made in consultation because the page is taking over 20 seconds to display the result.
Can anyone help me? Below the code I'm using.
// SEARCH FROM ALL CUSTOM FIELDS
$post_ids_meta = $wpdb->get_col( $wpdb->prepare( "
ALTER TABLE wp_posts ADD INDEX (postmeta)
SELECT DISTINCT post_id FROM {$wpdb->postmeta}
WHERE meta_value LIKE '%s'
", $keyword ) );
// SEARCH FOR TITLE AND CONTENT
$post_ids_post = $wpdb->get_col( $wpdb->prepare( "
ALTER TABLE wp_post s ADD INDEX (posts);
SELECT DISTINCT ID FROM {$wpdb->posts}
WHERE post_title LIKE '%s'
OR post_content LIKE '%s'
", $keyword, $keyword ) );
$post_ids = array_merge( $post_ids_meta, $post_ids_post );
UPDATE:
Try this one. It's not tested but I'm sure it will work if you check and fix it a little bit:
// SEARCH IN title, content and meta_value
$post_ids = $wpdb->get_col( $wpdb->prepare( "
SELECT DISTINCT ID FROM {$wpdb->posts} AS p,
LEFT JOIN {$wpdb->postmeta} AS m,
ON m.post_id = p.ID
WHERE p.post_type = '%s'
AND (
post_title LIKE '%%s%'
OR m.meta_value LIKE '%%s%'
OR post_content LIKE '%%s%')
", $post_type, $keyword, $keyword, $keyword) );
Note:
Assume you have taken input $post_type & $keyword. Eg: $post_type = "fairs";
I added % before and after %s to make sure it's widecard search.
In this case, I use DISTINCT because the joint table have repeated IDs. My apologies for the previous fault assumption on your first query that it was not needed.
Speed is not guaranteed, since you are doing a widecard search on post_content which is not indexed.
You should make sure the meta_value field is indexed for a little faster speed. If you meta don't store too much text in it.
GOOD LUCK!
ORIGINAL:
Firstly, let's clarify these:
Remove these 2 lines as it won't help (it make it worse due to repeated call):
ALTER TABLE wp_posts ADD INDEX (postmeta)
And
ALTER TABLE wp_posts ADD INDEX (posts);
ID is already distinct. So it won't help you do: SELECT DISTINCT ID
The final queries should look like these:
// SEARCH FROM ALL CUSTOM FIELDS
$post_ids_meta = $wpdb->get_col( $wpdb->prepare( "
SELECT post_id FROM {$wpdb->postmeta}
WHERE meta_value LIKE '%s'
", $keyword ) );
// SEARCH FOR TITLE AND CONTENT
$post_ids_post = $wpdb->get_col( $wpdb->prepare( "
SELECT ID FROM {$wpdb->posts}
WHERE post_title LIKE '%s'
OR post_content LIKE '%s' // Remove this will boost performance by 90% because post_content is not indexed
", $keyword, $keyword ) );
$post_ids = array_merge( $post_ids_meta, $post_ids_post );
What I recommend is to use this plugin: https://wordpress.org/plugins/search-everything/
Assuming that $keyword has no wildcards, you might try expressing this query as:
SELECT ID
FROM {$wpdb->posts}
WHERE post_title LIKE '%s'
UNION
SELECT ID
FROM {$wpdb->posts}
WHERE post_content LIKE '%s';
MySQL might figure out to use the indexes for this. The indexes that you want are:
create index wp_post_title_id on wp_post(post_title, id);
create index wp_post_content_id on wp_post(post_content, id);
This assumes that{$wpdb->posts} is really wp_post.

Remove _thumbnail_id from all custom post type

I need to remove the _thumbnail_id meta key data from a custom post type in my wordpress database. I found this code which will allow me to remove it from everything, but I don't want it to remove it from my posts, just my custom post type called "svg" would anyone be able to help me adjust the code to do so?
global $wpdb;
$attachments = $wpdb->get_results( "
SELECT *
FROM $wpdb->postmeta
WHERE meta_key = '_thumbnail_id'
" );
foreach ( $attachments as $attachment ) {
wp_delete_attachment( $attachment->meta_value, true );
}
$wpdb->query( "
DELETE FROM $wpdb->postmeta
WHERE meta_key = '_thumbnail_id'
" );
Or if you guys know a better way to remove the _thumbnail metakey from just SVG posts let me know as I have over 400+ svg posts and can't go through each one.
Are you looking for something like this?
DELETE m
FROM wp_postmeta m JOIN wp_posts
ON m.post_id = p.id
WHERE p.post_type = 'svg'
AND meta_key = '_thumbnail_id'
Note: before you try to delete anything make sure that you have solid backup of your database just in case.
First , your code will first delete all attachments ,and then clean (not only clean the _thumbnail_id ) -
Anyhow , in general lines , something like this should work :
SELECT FROM 'wp_posts', WHERE 'post_type' = 'my_post_type'
INNER JOIN 'wp_postmeta' ON 'wp_post.post_id' = 'wp_postmeta.post_id'
AND 'meta_key'='my_meta_key'
// AND 'meta_value'= my_value'// this line only if needed ...
BACKUP YOUR DATABASE .
I take no responsibility for such an action.
Change SELECT with DELETE after verification...
The last line is only for demonstration, in your case I assume you do not need it - so delete accordingly ..

Categories