sql statement for wordpress query - mysql

im trying to extract the following fields from a local wordpress installation
post_title
image_url
post_excerpt
other criteria for the SELECT is:
the status is publish
it's a post item
and the results only come from the projects parent category or any subcategory of project
i've got this far already but am finding it difficult to workout the rest
SELECT DISTINCT wp_posts.post_title, wp_postmeta.meta_value
FROM wp_posts, wp_term_relationships, wp_term_taxonomy, wp_postmeta
WHERE wp_term_relationships.object_id = wp_posts.ID
AND post_status = 'publish'
AND post_type = 'post'
AND wp_postmeta.meta_key = 'image_url'
AND wp_term_taxonomy.parent = 5
ORDER BY wp_posts.post_date DESC
as per the below comment, table for wp_term_taxonomy is:
term_taxonomy_id || term_id || taxonomy || description || parent || count
as per the below comment, table for wp_posts is:
ID || post_author || post_date || post_content || post_title|| post_excerpt || post_status
there are more, but not relevant here
as per the below comment, table for wp_term_relationships is:
object_id ||term_taxonomy_id || term_order
as per the below comment, table for wp_postmeta is:
meta_id || post_id || meta_key || meta_value

Always try to use the functions provided by WordPress to fulfill the requirements. Yes, the images( image urls ) are stored inside wp_posts table as attachments.
<?php
$args = array(
'post_type' => 'attachment',
'post_mime_type' => 'image',
'numberposts' => -1,
'post_status' => null,
'post_parent' => $post->ID
);
$attached_images = get_posts( $args );
?>
use this wordpress function to get post image url pass the post id to function it result the url of image. http://codex.wordpress.org/Function_Reference/wp_get_attachment_url
wp_get_attachment_url( $id );
However, if you want to go against something that is built in, you can try the following, however I must say I have no local version of wordpress to test against at the moment.
SELECT p.post_title as post_title, p.post_excerpt as post_excerpt,( 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'
Let me know if you need anything more and I will install a local wordpress installation and do it with you through a chat session.

Related

Woocommerce query return products, order by total_sales

I've checked the woocommerce reports and products that haven't been sold are being fetched in the query?
Here is the query:
SELECT wp_terms.name as categoryname,v1.meta_value as thevalue, wp_terms.slug as categoryslug, wp_posts.post_title as mytitle, wp_terms.term_id as categoryid,wp_term_taxonomy.parent as categoryparent FROM wp_posts
INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
INNER JOIN wp_term_taxonomy ON (wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id)
INNER JOIN wp_terms ON (wp_term_taxonomy.term_id = wp_terms.term_id)
INNER JOIN wp_postmeta v1 ON (wp_posts.ID = v1.post_id) AND v1.meta_key LIKE 'total_sales'
WHERE wp_posts.post_status = 'publish' AND wp_posts.post_type = 'product' AND wp_terms.slug='garden-lighting' AND wp_posts.post_title NOT LIKE '%cable%' AND v1.meta_value !=0
ORDER BY v1.meta_value DESC
LIMIT 8
I checked the results of the array returned and products that haven't been sold are returning with a total_sales value?
Where did i go wrong? I want products returned for a specific category and ordered by total sales.
Why not use WP_Query instead of trying to write an SQL statement?
If I've understood you correctly, the following should return the first 8 posts in the 'garden-lighting' category sorted by sales and then by title.
$args = array(
'query_id' => 'exclude_cable',
'post_type' => 'product',
'post_status' => 'publish',
'category_name' => 'garden-lighting',
'posts_per_page' => 8,
'orderby' => array( 'meta_value_num' => 'DESC', 'title' => 'ASC' ),
'meta_key' => 'total_sales'
);
$new_query = new WP_Query( $args );
Edit I have added a few extra parameters. One I forgot to designate the product post type! Oops. But additionally, I have added a query_id parameter. WordPress doesn't do anything with this by default, but we can filter the posts_where clause and use it there to only modify the posts_where for this specific query.
add_filter( 'posts_where' , 'so_28478323_posts_where', 10, 2 );
function so_28478323_posts_where( $where, $q ) {
if ( 'exclude_cable' == $q->get( 'query_id', null ) ) {
$where .= " AND wp_posts.post_title NOT LIKE '%cable%'";
}
return $where;
}

Wordpress SQL query to fetch the meta_key names in a custom post type

Using WP dataTables plugin and my MySQL sucks so please bear with me.
I'm trying to fetch multiple associated meta_keys (custom field names) that are allocated to a custom post type in WordPress, and display the fields as the table header with the custom field values in the rows underneath the header.
My SQL below kinda works. While it pulls in a colum called 'meta_key' and 'meta_value', it has the actual names of the key as it's data. I want the meta_key value itself as the list returned.
SELECT * FROM wp_posts INNER JOIN wp_postmeta
ON wp_posts.ID = wp_postmeta.post_id
WHERE 1=1 AND wp_posts.post_type = 'my_custom_post'
AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')
AND (wp_postmeta.meta_key = 'call_date' OR wp_postmeta.meta_key = 'call_time' OR wp_postmeta.meta_key = 'caller_number' OR wp_postmeta.meta_key = 'call_duration' OR wp_postmeta.meta_key = 'call_status' )
ORDER BY wp_posts.menu_order, wp_posts.post_date DESC LIMIT
So this creates a table with the header as 'meta_key' but I want the custom field name itself as the header. Hope this makes sense.
PS I've also tried
SELECT caller_number, call_duration, call_status, call_date, call_time
FROM wp_posts
WHERE post_type = 'my_custom_post'
AND post_status = 'publish'
FROM wp_postmeta
WHERE post_id = post_id
But it shows no data...
Seriously, any help here would be awesome.
for specific keys
get_post_meta($postid, '_metakey', single);
for all keys
get_post_meta($postid);
so you can do a foreach loop if you return just the custom posts in your sql query. But for posts, wp_query does a good job of returning posts rather than custom mysql queried.
See what is all returning...
global $wpdb;
global $post;
$cpt = "my_custom_post";
$sql = "SELECT * FROM {$wpdb->prefix}posts INNER JOIN {$wpdb->prefix}postmeta
ON {$wpdb->prefix}posts.ID = {$wpdb->prefix}postmeta.post_id
WHERE 1=1 AND {$wpdb->prefix}posts.post_type = '$cpt'
AND ({$wpdb->prefix}posts.post_status = 'publish' OR {$wpdb->prefix}posts.post_status = 'private')
AND ({$wpdb->prefix}postmeta.meta_key = 'call_date' OR {$wpdb->prefix}postmeta.meta_key = 'call_time' OR {$wpdb->prefix}postmeta.meta_key = 'caller_number' OR {$wpdb->prefix}postmeta.meta_key = 'call_duration' OR {$wpdb->prefix}postmeta.meta_key = 'call_status' )
ORDER BY {$wpdb->prefix}posts.menu_order, {$wpdb->prefix}posts.post_date DESC";
$data = $wpdb->get_results($sql);
echo "<pre>";
var_dump($data);
echo "</pre>";
die();

Wordpress Query order by custom field missing posts

This is my current query:
query_posts(array_merge(array('tag' => $pagetag,'meta_key'=>priority,'orderby' =>meta_value, 'order' =>'ASC','paged' => get_query_var('paged'))));
My problem is that the query shows me only the post that has values for my 'meta_key' meaning that 'priority' is not NULL.
How can I improve this query so that it will still orderby my meta_key but will show all the posts that aren't NULL as well?
Thanks in advance!
The problem is that WordPress adds an INNER JOIN to the wp_postmeta table as soon as you mention meta_key in your conditions. One way around the problem is to add a filter on the order by clause, something like this:
function so_orderby_priority($original_orderby_statement) {
global $wpdb;
return "(SELECT $wpdb->postmeta.meta_value
FROM $wpdb->postmeta
WHERE $wpdb->posts.ID = $wpdb->postmeta.post_id
AND $wpdb->postmeta.meta_key = 'priority') ASC";
}
add_filter('posts_orderby', 'so_orderby_priority');
query_posts(
array(
'tag' => $pagetag,
'paged' => get_query_var('paged')
)
);
remove_filter('posts_orderby', 'so_orderby_priority');
Note MySQL sorts NULLs first - if you want them sorted last, try something like this (assuming all your priorities come before ZZZZZ alphabetically):
function so_orderby_priority($original_orderby_statement) {
global $wpdb;
return "IFNULL(
(SELECT $wpdb->postmeta.meta_value
FROM $wpdb->postmeta
WHERE $wpdb->posts.ID = $wpdb->postmeta.post_id
AND $wpdb->postmeta.meta_key = 'priority'),
'ZZZZZ') ASC";
}
Edit
Here's a bit more explanation, which assumes you understand SQL at least a bit.
Your original query_posts resulted in the following query running against the database:
SELECT wp_posts.*
FROM wp_posts
INNER JOIN wp_term_relationships ON ( wp_posts.id = wp_term_relationships.object_id )
INNER JOIN wp_postmeta ON ( wp_posts.id = wp_postmeta.post_id )
WHERE 1 = 1
AND ( wp_term_relationships.term_taxonomy_id IN ( 3 ) )
AND wp_posts.post_type = 'post'
AND ( wp_posts.post_status = 'publish'
OR wp_posts.post_status = 'private' )
AND ( wp_postmeta.meta_key = 'priority' )
GROUP BY wp_posts.id
ORDER BY wp_postmeta.meta_value ASC
LIMIT 0, 10;
That INNER JOIN wp_postmeta is what removed any posts without a priority from your results.
Removing the meta_* related conditions from your query_posts:
query_posts(
array(
'tag' => $pagetag,
'paged' => get_query_var('paged')
)
);
solved that problem, but the sort order is still wrong. The new SQL is
SELECT wp_posts.*
FROM wp_posts
INNER JOIN wp_term_relationships ON ( wp_posts.id = wp_term_relationships.object_id )
WHERE 1 = 1
AND ( wp_term_relationships.term_taxonomy_id IN ( 3 ) )
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 wp_posts.post_date DESC
LIMIT 0, 10;
The posts_orderby filter allows us to change the ORDER BY clause: wp_posts.post_date DESC gets replaced by what the filter returns. The final SQL becomes:
SELECT wp_posts.*
FROM wp_posts
INNER JOIN wp_term_relationships ON ( wp_posts.id = wp_term_relationships.object_id )
WHERE 1 = 1
AND ( wp_term_relationships.term_taxonomy_id IN ( 3 ) )
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 (SELECT wp_postmeta.meta_value
FROM wp_postmeta
WHERE wp_posts.id = wp_postmeta.post_id
AND wp_postmeta.meta_key = 'priority') ASC
LIMIT 0, 10
which does what you're after.
I needed to perform a similar task on the users.php page for a custom column I added and used the following code that I modified from Hobo
add_action('pre_user_query', 'qd_users_column_orderby');
function qd_users_column_orderby($userquery){
if('my_last_login'==$userquery->query_vars['orderby']) { //check if my cusomt meta_key is the column being sorted
global $wpdb;
$userquery->query_orderby = " ORDER BY(SELECT $wpdb->usermeta.meta_value
FROM $wpdb->usermeta
WHERE $wpdb->users.ID = $wpdb->usermeta.user_id
AND $wpdb->usermeta.meta_key = 'my_last_login') ".($userquery->query_vars["order"] == "ASC" ? "asc " : "desc ")." , wp_users.user_login ".($userquery->query_vars["order"] == "ASC" ? "asc " : "desc ");
}
}
Hopefully this helps somebody in need of this information.
In an effort of being throughout, the remainder of the necessary code to complete my individual task is below.
add_filter('manage_users_columns', 'qd_add_user_login_column');
function qd_add_user_login_column($columns) {
$columns['my_last_login'] = 'Last Logged In';
return $columns;
}
add_action('manage_users_custom_column', 'qd_show_user_login_column_content', 10, 3);
function qd_show_user_login_column_content($value, $column_name, $user_id) {
$user = get_userdata( $user_id );
if ( 'my_last_login' == $column_name ){
$lastLogin = get_the_author_meta('my_last_login', $user_id);
if(!$lastLogin){
return "Never";
}else{
date_default_timezone_set(get_option('timezone_string'));
return date('m/d/y g:ia', $lastLogin);
}
}
return $value;
}
add_filter( 'manage_users_sortable_columns', 'qd_users_table_sorting' );
function qd_users_table_sorting( $columns ) {
$columns['my_last_login'] = 'my_last_login';
return $columns;
}
The Issue: Sorting by a custom field without excluding posts that don't have a value set for that custom field.
Hobo's answer explains this well. Here I'm just going to offer a simpler alternative that ended up being easier in my case (Please note this won't work correctly if pagination is needed).
I decided to do the sorting in PHP after the query is made.
The nice part is that I have better control over where the posts with null values end up (I wanted them to show up last).
$query = new WP_Query($args);
//sort by rank
function customSort($a, $b)
{
$a = get_field("sort_ranking", $a);
$b = get_field("sort_ranking", $b);
//handle nulls
$a = is_numeric($a) ? $a : 9999;
$b = is_numeric($b) ? $b : 9999;
if ($a == $b) return 0;
return ($a < $b) ? -1 : 1;
}
usort($query->posts, "customSort");
Here I have a numeric custom field called sort_ranking and I'm using it to sort ASC. Posts with a null value for this field are assigned 9999 so that they end up at the end. (Note: I'm using ACF, hence the get_field function)
Hope this helps someone!
The easiest way to do this is to insert the custom field using save_post action, so every post published will have its own meta_key with a default value.
Use a MySQL query for add post_meta to all posts has not the meta. Thats it.
If you/anyone need code help on this, just reply :)
UPDATE
As Timusan asked, add this code in your functions.php file after changing the meta-key name :
add_action('save_post', 'sidati_post_views_metakey');
function sidati_post_views_metakey ($post_id){
/*
* $post_id = is the post ID
* 'sidati_post_views' => is your metakey name (sidati is prefix always nice to add your prefix)
* 0 => the inital value
* true => (bool) add true if you want this metakkey become unique
*/
add_post_meta($post_id, 'sidati_post_views', 0, true);
}
// THIS ACTION MUST RUN ONLY ONE TIME
add_action('init', 'sidati_allposts_must_have_this');
function sidati_allposts_must_have_this(){
/* Call the WordPress DataBase class */
global $wpdb;
/* This Query will get us all the posts and pages without "sidati_post_views" metakey. */
$ids = $wpdb->get_row("SELECT ID FROM wpdb->posts WHERE post_type IN ('post', 'page') AND post_status = 'publish' AND ID NOT IN (SELECT post_id FROM $wpdb->postmeta WHERE meta_key = 'sidati_post_views')");
/* After get all posts/pages, now you need to add the meta keys (this may take a few munites if you have many posts/pages)*/
foreach ($ids as $post_id) {
add_post_meta($post_id, 'sidati_post_views', 0, true);
}
}

How to manually query posts title, content and image attachment thumbnail?

I am trying to manually query from an external php file the wordpress database and I want to extract the last 3 posts with: title, content, last (or first) image, and for that image, from wp_postmeta I want to get the thumbnail url.
I managed to get the title, content, image id, but I couldn't figure it out how to add another join for getting image thumbnail. This is what I have:
SELECT a.post_title title, max(c.guid) img_url, a.ID id
FROM wp_posts a
LEFT JOIN
(select post_parent, max(post_date_gmt) as latest_image_date from wp_posts
where post_type='attachment' GROUP BY post_parent) b
on a.id=b.post_parent
LEFT JOIN wp_posts c
on c.post_parent=a.id
and c.post_type='attachment'
and b.latest_image_date = c.post_date_gmt where c.guid IS NOT NULL
GROUP BY a.post_title ORDER BY a.ID
The image thumbnail is in wp_postmeta (meta_id, post_id, meta_key, meta_value) table, looking like this: 58435, 6711, _wp_attachment_metadata, a:6:{s:5:"width";s:4:"1024";s:6:"height";s:3:"683"...
I could see I get the image id in c.id and all it needs is another JOIN to also get data from wp_postmeta for the field where meta_key="_wp_attachment_metadata" and post_id=c.id.
Can anyone help me with completing the query? Thanks!
I know this is an old post, but here to help future answer seekers
Update the query as needed. This current query will select post that have attachments. It returns the attachment ID and guid, the post ID and title along with the category name and term_id.
SELECT DISTINCT p.ID,p.post_title, a.ID as attach_id, a.guid, t.name, t.term_id FROM $wpdb->posts as a
LEFT JOIN $wpdb->posts as p on p.ID = a.post_parent
AND a.post_type = 'attachment' AND a.post_mime_type = 'image/png'
JOIN $wpdb->term_relationships as tr on tr.object_id = p.ID
JOIN $wpdb->terms as t on t.term_id = tr.term_taxonomy_id
JOIN $wpdb->term_taxonomy as tt on tt.term_id = t.term_id
AND tt.taxonomy = 'category'
AND p.post_type = 'post'
AND p.post_status = 'publish';
You should save your time and use wordpress functions :
make a plugin
or include wp-load.php in your script
https://wordpress.stackexchange.com/questions/47049/what-is-the-correct-way-to-use-wordpress-functions-outside-wordpress-files
In the end I chose another solution (at least temporary) because it adds horizontal capabilities: I created a completely empty custom page (I had to manually remove some actions/filters to get it empty) in the other site (the one to be included) which exports data in json format. I get that data and print it as I need in the current site.
<?php
$args= array(
'posts_per_page' => 6
//if there are sticked posts they will also appear beside the 2 if we run this in a separate php file, not included in theme
);
$ii = 0;
query_posts($args);
if( have_posts() ) :
while ( have_posts() ) : the_post();
$permalink = get_permalink();
$titlu = get_the_title();
$excerpt = get_the_excerpt();
$args = array(
'post_type' => 'attachment',
'post_parent' => $post->ID,
'post_status' => 'inherit',
'numberposts' => 1
);
$images = get_posts($args);
$j = 1;
foreach ($images as $i) :
$ii++;//am preluat doar o poza, e ok numaratoarea
$j++;
$poza_thumb = wp_get_attachment_image_src($i->ID, 'thumbnail');
$arr[$ii] = array('titlu' => $titlu, 'url' => $permalink, 'poza_thumb' => "".$poza_thumb[0], 'poza_width' => "".$poza_thumb[1], 'poza_height' => "". $poza_thumb[2], 'articol' => $excerpt);
endforeach;
endwhile;
echo json_encode($arr);//we send json as array
else :
endif;?>

Advanced MySQL query in Wordpress with JOIN

I am new to MySQL and I am trying to write a quite advanced query. But hey! Learning by doing & Stackoverflow!
I could probably get all data in a less advanced query/queries and sort the data using PHP. But I figure it could be done directly in the query.
Below is my code. Please ask question if you don't understand and I will try to explain better. And please help me correct the code if you find any errors.
The code will be used to display different fields on my wordpress pages. Different fildes will have different categories eg. sidebar-blog, sidebar-page, highlight-blog, highlight-page. It will work almost like regular posts.
Here is the database structure of Wordpress:
http://codex.wordpress.org/images/9/9e/WP3.0-ERD.png
http://codex.wordpress.org/Database_Description
Questions:
How am I supose to join the tables: wp_posts, wp_term_relationships, wp_term_taxonomy, wp_terms AND wp_postmeta?
Is it good practice to make advanced queries or should you use PHP to handle if/else functions?
<?php
$id = $post->ID; // Gets the ID of current page
$query = "
SELECT wp_posts.post_content, wp_posts.ID, wp_terms.slug # Data from two different tables
FROM wp_posts
# Cant figure out how to join the tables
INNER JOIN wp_postmeta
ON wp_posts.ID = wp_postmeta.post_id
INNER JOIN wp_term_relationships
ON wp_posts.ID = wp_term_relationships.object_id
INNER JOIN wp_term_taxonomy
ON wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id
INNER JOIN wp_terms
ON wp_term_taxonomy.term_id = wp_terms.term_id
WHERE
wp_posts.post_type = 'my-own-post-type' # Only get specific post-type
AND
wp_posts.post_status = 'publish' # Only get published posts
AND
# START - Only get categories specified here
(
wp_terms.slug = 'category-1'
OR
wp_terms.slug = 'category-2'
OR
wp_terms.slug = 'category-3'
OR
wp_terms.slug = 'category-4'
OR
wp_terms.slug = 'category-5'
)
# END - Only get categories specified here
AND
# I want to be able to include or exclude specific pages, even if category is the right one
# Exlude = Don't get data if current page ID is found (ID of current page will be checked in meta_value using %,$id,%)
# Include means: If include value is specifyed, then get data ONLY if ID is found (ID of current page will be checked in meta_value using %,$id,%)
# If not exclude and include are set, it should get the data
# START - Include exclude
(
# exclude is set, so check if page id match anywhere. If it IS found it it should not get the data, otherwise YES
wp_postmeta.meta_key = 'exclude' AND wp_postmeta.meta_value <> '%,$id,%'
OR
# include is set, so check if page id match anywhere. If it IS NOT found it it should not get the data, otherwise YES
wp_postmeta.meta_key = 'include' AND wp_postmeta.meta_value = '%,$id,%'
OR
# If exclude and include aren't set it should get the data
wp_postmeta.meta_key <> 'exkludera' AND wp_postmeta.meta_key <> 'include'
)
# END - Include exclude
";
$result = mysql_query($query);
while($row = mysql_fetch_array($result))
{
// collect all fields in category 1 (eg. sidebar)
if($row['slug'] == 'category-1'){
$all_fields_from_category_1 = $all_fields_from_category_1.'
<div id="field-sidebar">
'.$row['post_content'].'
</div>
';}
// collect all fields in category 1 (eg. highlight)
if($row['slug'] == 'category-2'){
$all_fields_from_category_2 = $all_fields_from_category_2.'
<div id="field-highlight">
'.$row['post_content'].'
</div>
';}
} // end while
// sidebar
echo '<div id="container-sidebar">'.
$all_fields_from_category_1.
'</div>';
// highlight
echo '<div id="container-highlight">'.
$all_fields_from_category_1.
'</div>';
?>
New version, new question:
SELECT DISTINCT wp_posts.post_content, wp_posts.ID, wp_terms.slug
FROM wp_posts
JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id
JOIN wp_term_relationships ON wp_posts.ID = wp_term_relationships.object_id
JOIN wp_term_taxonomy ON wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id
JOIN wp_terms ON wp_term_taxonomy.term_id = wp_terms.term_id
WHERE wp_posts.post_type = 'my-own-fields'
AND wp_posts.post_status = 'publish'
AND wp_terms.slug IN
('field1', 'field2', 'field3', 'field4', 'field5', 'field6')
AND
(
wp_postmeta.meta_key = 'exlude' AND wp_postmeta.meta_value <> '$id'
OR wp_postmeta.meta_key = 'include' AND wp_postmeta.meta_value = '$id'
OR wp_postmeta.meta_key <> 'exlude' AND wp_postmeta.meta_value <> 'include' #LAST ROW
)
The "#LAST ROW" gives me back data even if exclude or include is set. Thats becauce it matches two other rows in the table wp_postmeta.
Example of table wp_postmeta:
meta_id post_id meta_key meta_value
1 30 include 18
2 30 _edit_lock 1322225789:1
3 30 _edit_last 1
If meta_key inklude or exclude cant be found for the post_id I want to return the data...
Example senario when I want to return the data:
meta_id post_id meta_key meta_value
2 30 _edit_lock 1322225789:1
3 30 _edit_last 1
Any idea of how I can solve this?
A statement that say: If no rows with exclude or include was found for current id. Return the data.
More examples:
The post_id is 30.
If senario is:
meta_id post_id meta_key meta_value
1 30 include 18
2 30 _edit_lock 1322225789:1
3 30 _edit_last 1
Then I want to get back wp_posts.post_content, wp_posts.ID and wp_terms.slug AS LONG AS $id IS 18.
If senario is:
meta_id post_id meta_key meta_value
1 30 exclude 18
2 30 _edit_lock 1322225789:1
3 30 _edit_last 1
Then I want to get back wp_posts.post_content, wp_posts.ID and wp_terms.slug AS LONG AS $id IS NOT 18.
If senario is:
meta_id post_id meta_key meta_value
2 30 _edit_lock 1322225789:1
3 30 _edit_last 1
Then I want to get back wp_posts.post_content, wp_posts.ID and wp_terms.slug.
Your joins are done correctly. When removing your comments and extra lines, you will see that the query is not really that complicated. The only real change I made was to change your list of OR for wp_terms.slug to an IN statement. This was only done to reduce code duplication, clean up the look, not to change functionality.
SELECT p.post_content, p.ID, t.slug
FROM wp_posts AS p
INNER JOIN wp_postmeta AS pm ON p.ID = pm.post_id
INNER JOIN wp_term_relationships AS tr ON p.ID = tr.object_id
INNER JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
INNER JOIN wp_terms AS t ON tt.term_id = t.term_id
WHERE p.post_type = 'my-own-post-type'
AND p.post_status = 'publish'
AND t.slug IN
('category-1', 'category-2', 'category-3', 'category-4', 'category-5')
AND
(
( pm.meta_key = 'exclude' AND pm.meta_value <> '$id' )
OR ( pm.meta_key = 'include' AND pm.meta_value = '$id' )
OR ( pm.meta_key <> 'exclude' AND pm.meta_value <> 'include' )
)