Pull post from a specific Wordpress category - php

im looking to pull 3 posts from a specific Wordpress Category. At the minute I can pull 3 latest posts and display them in a flash banner using the code below.
SELECT yah_posts.*, yah_postmeta.*
FROM yah_posts
LEFT JOIN yah_postmeta ON yah_posts.ID = yah_postmeta.post_id
WHERE yah_postmeta.meta_key = 'largeimage' && yah_posts.post_status = 'publish'
ORDER BY post_date DESC LIMIT 3
I want to be able to pull 3 latest posts from a specific category instead of just 3 latest posts from every category.
I have put together this code below, but it doesn't seem to be working :(
$query = "SELECT yah_posts.*, yah_postmeta.*
FROM yah_posts
LEFT JOIN yah_postmeta ON yah_posts.ID = yah_postmeta.post_id
AND LEFT JOIN $yah_term_taxonomy ON($yah_term_relationships.term_taxonomy_id = $yah_term_taxonomy.term_taxonomy_id)
WHERE yah_postmeta.meta_key = 'largeimage' && yah_posts.post_status = 'publish'
AND $yah_term_taxonomy.term_id = '1'
AND $yah_term_taxonomy.taxonomy = 'category'
ORDER BY post_date DESC LIMIT 3";

There is actually a stack exchange site just focused on wordpress questions. Looking there and taking code from this question:
https://wordpress.stackexchange.com/questions/6533/modify-wordpress-sql-query-to-pull-from-within-a-category
You would need to add another JOIN:
LEFT JOIN $wpdb->term_taxonomy ON($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)
And a couple more statements in your WHERE clause:
AND $wpdb->term_taxonomy.term_id = {term_id of the category you want}
AND $wpdb->term_taxonomy.taxonomy = 'category'

You can use wp_term_relationships in your query, take a look at wp_terms and wp_term_relationships tables in your database.

Related

How to display several subcategories and their news in one query?

I have a news site and I am trying to include a block of news in it.
see the image please
I created a category call world news and added subcategories. (Travel, News, Art, Bussines)
I display them one by one, I mean I do a query for each news, that means 4 different queries like below :
$sql = "SELECT posts.post_catId,
posts.post_seo_url,
posts.post_desc,
posts.post_type,
posts.post_status,
posts.post_title,
posts.post_image_url,
categories.catId,
categories.catName,
categories.cat_seo_url
FROM posts
LEFT JOIN categories
ON posts.post_catId = categories.catId
WHERE post_catId = catId AND cat_seo_url = 'art'
AND post_status = ?
ORDER BY post_created_at DESC LIMIT 1";
$stmt = $pdo->prepare($sql);
$stmt->execute(['1',]);
if($stmt->rowCount() > 0){
while($row = $stmt->fetch()){
//here
}
}
My question is: is there a way to display them in one query ?
Edit : I want to display 1 news from 4 specific categories with one query instead of 4.
I know I can add a new row to categories table to secify which categories can be displayed.
You 'invert' the query, selecting the categories first and then joining to the posts table, constraining it by the post_seo_url field, like so:
$sql = "SELECT
categories.catId,
categories.catName,
categories.cat_seo_url,
posts.post_catId,
posts.post_seo_url,
posts.post_desc,
posts.post_type,
posts.post_status,
posts.post_title,
posts.post_image_url,
FROM categories
JOIN posts ON posts.post_seo_url = (
SELECT p.post_seo_url FROM posts as p
WHERE categories.catId = p.post_catId
ORDER BY p.post_created_at DESC LIMIT 1
)
WHERE post_status = ?"
Here's a method using ROW_NUMBER() function:
SELECT p.*,
categories.catId,
categories.catName,
categories.cat_seo_url
FROM
(SELECT
ROW_NUMBER() OVER (PARTITION BY posts.post_catId ORDER BY posts.post_created_at DESC) AS RN,
posts.post_catId,
posts.post_seo_url,
posts.post_desc,
posts.post_type,
posts.post_status,
posts.post_title,
posts.post_image_url
FROM posts
WHERE post_status = ? ) p
JOIN categories
ON p.post_catId = categories.catId
WHERE RN=1;
I've made the query on posts table to become a subquery with addition of ROW_NUMBER() function then JOIN it with categories table and added WHERE that only return row number = 1. I've changed the LEFT JOIN to JOIN because I don't see any reason to use LEFT JOIN in this operation. However, if there is a reason, please update it in your question.
Here's a demo fiddle

Wordpress query for posts is pulling up revisions as results

I have the following wordpress query which is displaying the post title multiple times, I have checked and it's getting all the revisions for each post.
Here is the query:
SELECT DISTINCT post_title, ID
FROM wpblog_posts
WHERE post_title LIKE '%Kimberley%'
OR post_title LIKE '%Camping%'
AND wpblog_posts.post_type = 'post'
AND post_status = 'publish'
ORDER BY post_title DESC LIMIT 0, 6;
Anyone know why this might be happening.
Update
Removed from query string as not relevant and will make it
easier to debug.
LEFT JOIN wpblog_term_relationships rel ON rel.object_id = wpblog_posts.ID
LEFT JOIN wpblog_term_taxonomy tax ON tax.term_taxonomy_id = rel.term_taxonomy_id
LEFT JOIN wpblog_terms t ON t.term_id = tax.term_id
Cheers
Check this query if it works for you:
SELECT DISTINCT post_title, ID
FROM wpblog_posts
WHERE (post_title LIKE '%Kimberley%' OR post_title LIKE '%Camping%')
AND wpblog_posts.post_type = 'post'
AND post_status = 'publish'
ORDER BY post_title DESC LIMIT 0, 6;
The query was looking for posts LIKE '%Kimberley%' - any type of post OR LIKE '%Camping%' AND wpblog_posts.post_type = 'post' ....

Custom $wpdb Posts filtered by Taxonomy Meta

Working on a complex set up where we have 2 separate Wordpress installs on the same database with different prefixes.
I need to make some queries for products from Site A for Site B.
Gotten a little rusty with my SQL as I mainly use built in WP functions.
On site A I'm using get_terms using a meta query to loop through a taxonomy and then making another query on the posts for each.
On Site B I'd like to do 1 custom $wpdb query and have it almost working where I'm checking a post meta value and then ordering by the taxonomy name like so:
$querystr = "
SELECT $tsm_posts.*, $siteA_terms.name, $siteA_terms.slug, tax2.description
FROM $siteA_posts, $siteA_postmeta
INNER JOIN {$siteA_term_relationships} AS rel2 ON $siteA_postmeta.post_id = rel2.object_id
INNER JOIN {$siteA_term_taxonomy} AS tax2 ON rel2.term_taxonomy_id = tax2.term_taxonomy_id
INNER JOIN {$siteA_terms} USING (term_id)
WHERE $siteA_posts.ID = $siteA_postmeta.post_id
AND $siteA_postmeta.meta_key = 'siteB_product'
AND $siteA_postmeta.meta_value = 'yes'
AND $siteA_posts.post_status = 'publish'
AND $siteA_posts.post_type = '" . SP_PRODUCTS . "'
AND $siteA_posts.post_parent = '0'
GROUP BY rel2.object_id
ORDER BY GROUP_CONCAT({$siteA_terms}.name ORDER BY name ASC)";
$siteA_products = $wpdb->get_results($querystr, OBJECT);
The one main issue I'm having is to also be able to filter by a taxonomy meta value as well as some categories are not meant to be displayed.
So I've been trying to do another INNER JOIN on the taxonomy meta table but I'm having issues and not getting the desired results:
INNER JOIN {$siteA_termmeta} AS taxMeta ON ( taxMeta.term_id = rel2.term_taxonomy_id AND taxMeta.meta_key = 'product_category_main' AND taxMeta.meta_value = 'YES' )
Any suggestions greatly appreciated.
So still having an issue with the taxonomy meta but I was able to achieve the results I was after by limiting the taxonomy itself and have cleaned up the code adding specific calls to needed post meta as well incase anyone finds it useful :)
So this code filters by post meta and taxonomy and then orders the posts by the taxonomy title.
Note: Knocking off the rust on my SQL it's much easier to name the specific calls to Joins and the extra meta etc to make it easier to extract and identify.
$query = "
SELECT p.ID, p.post_title, p.post_content,
fi_id.meta_value AS featured_id, taxable.meta_value AS taxable,
producer.name AS producer_name, producer.slug AS producer_slug, producer_tax.description AS producer_description
FROM {$siteA_posts} p
LEFT JOIN {$siteA_postmeta} fi_id ON fi_id.post_id = p.ID AND fi_id.meta_key = '_thumbnail_id'
LEFT JOIN {$siteA_postmeta} taxable ON taxable.post_id = p.ID AND taxable.meta_key = 'taxable'
LEFT JOIN {$siteA_postmeta} loc ON loc.post_id = p.ID AND loc.meta_key = 'location_loftbox'
INNER JOIN {$siteA_term_relationships} AS rel2 ON loc.post_id = rel2.object_id
INNER JOIN {$siteA_term_taxonomy} AS producer_tax ON rel2.term_taxonomy_id = producer_tax.term_taxonomy_id AND producer_tax.taxonomy = 'producers'
INNER JOIN {$siteA_terms} AS producer USING (term_id)
WHERE p.ID = loc.post_id
AND loc.meta_key = 'siteB_product'
AND loc.meta_value = 'yes'
AND p.post_status = 'publish'
AND p.post_type = 'products'
AND p.post_parent = '0'
GROUP BY rel2.object_id
ORDER BY GROUP_CONCAT(producer.name ORDER BY name ASC)
";

WordPress Posts, order by custom table results

I have a blog that I need to re-order based on the number of values in a completely custom table. The reason I am not using meta data is a bit complex, but this is just what I need to do.
I just need to count the number of rows in the table wp_upvotes which have a postID that matches the ID of the WordPress blog post, and order it by most "upvotes" to least. This result should include the WordPress post even if there are no values in the wp_upvotes table.
The query I am trying is this:
$post = $wpdb->get_results("
SELECT wp_posts.*, COUNT(wp_upvotes.id) AS upvotes
FROM wp_posts
LEFT JOIN wp_upvotes
ON wp_posts.ID = wp_upvotes.postID
WHERE wp_posts.post_status = 'publish'
AND wp_posts.post_type = 'post'
ORDER BY upvotes DESC, wp_posts.date DESC
LIMIT $pageNum, $numToLoad
", ARRAY_A);
If you want to ensure that there is a match between each table, you are correct to use a LEFT JOIN - an easy way to think about it is that everything on the "left" (wp_posts) will be included, and things on the "right" (wp_upvotes) will be included if they have a match, otherwise null. Just using JOIN will ensure that rows from both tables will only be shown if there is a match.
My guess is that you need to include a GROUP BY p.ID to have each upvotes value specific to a particular post.
As a note, you also have an error using wp_posts.date instead of wp_posts.post_date;
It's also a good idea to use the $wpdb-posts and $wpdb-prefix properties in case you want to use this somewhere with a database prefix that is not wp_.
If you just want to see the results of the data in wp_posts you can just run a database query with an ORDER BY and return the columns, or if you want to use the WordPress filters (on things like the_title() and the_content() you can pass the post IDs into a WP_Query with the post_id__in and orderby=post__in arguments - you would need to reference back the $upvotes value by ID however.
global $wpdb;
$sql = <<<SQL;
SELECT p.*, COUNT(v.id) as upvotes
FROM {$wpdb->posts} p
JOIN {$wpdb->prefix}upvotes v
ON p.ID = v.postID
WHERE
p.posts_status = 'publish'
AND p.post_type = 'post'
GROUP BY p.ID
ORDER BY upvotes DESC, p.post_date DESC
LIMIT $pageNum, $numToLoad
SQL;
// use ARRAY_A to access as $row['column'] instead of $row->column
$rows = $wpdb->get_results( $sql );
foreach ( $rows as $row ){
$content = $row->post_content;
$upvotes = $row->upvotes;
}

SQL- how to extract forum topics that are not repeats?

On the home page of my website I want to display the latest posts to the forum however I don't want to show the same topic twice. How can I modify the code below to do this?
http://punbb.informer.com/wiki/punbb13/integration#recent_10_posts
Basically show the latest posts, but only once for each forum topic/thread.
Add a condition to keep only records where the post is the last post in the topic:
WHERE p.id = (
SELECT pp.id
FROM posts AS pp
WHERE pp.topic_id = t.id ORDER BY pp.posted DESC LIMIT 1
)
If you want only one value per topic, you could group by topic, and from each topic select the most recent post. Then, you could choose the top 10 topics.
I'll write it in SQL, and you can translate that to PHP:
SELECT p.id, p.message, o.subject
FROM
((SELECT t.id
FROM posts AS p LEFT JOIN topics AS t ON p.topic_id = t.id
GROUP BY t.id
HAVING p.posted = MAX(p.posted) ) ids LEFT JOIN topics AS t ON ids.id = t.id) o
LEFT JOIN posts AS p ON o.id = posts.topic_id
ORDER BY p.posted DESC
LIMIT '0,10'
change this line
'SELECT' => 'p.id, p.message, t.subject',
to
'SELECT DISTINCT' => 'p.id, p.message, t.subject',

Categories