UNION 2 sql queries - wp_posts vs wp_terms - PHP, WORDPRESS - php

I have a page where I'm displaying all taxonomy categories and all posts/pages. There I need to have ajax pagination so that my page won't load ages (or even not load). So I've built the pagination via sql query and now need to get both terms and posts with sql query, then union them so that my pagination will work properly and count including them all.
Here is my code:
$sql1 = "SELECT * FROM wp_term_taxonomy LEFT JOIN wp_terms ON (wp_term_taxonomy.term_id =
wp_terms.term_id) WHERE wp_term_taxonomy.taxonomy = 'product-category'";
$sql2 = "SELECT * FROM wp_posts WHERE (post_type = 'products' OR post_type = 'page')
AND (post_status = 'publish' OR post_status = 'suspended') AND ID NOT IN
(231, 236, 1070, 1245) order by post_title ASC";
$sql = $sql1." UNION ".$sql2;
$query = $sql . " limit " . $start . "," . $resultPerPage->perpage;
$list = $db_handle->runBackendQuery($query);
Above returns me following errors:
Warning: mysqli_fetch_object() expects parameter 1 to be mysqli_result, boolean given in .../dbcontroller.php on line 29
Warning: mysqli_num_rows() expects parameter 1 to be mysqli_result, boolean given in
.../dbcontroller.php on line 38
I think I can join such 2 different things. Is there anything I'm missing?

The error could happen because you have some error in your query for avoid this
You should select the same number of column and with corresponding data type so try avoiding select all (*) and use explicit select column you should use a sintax like eg:
$sql1 = "SELECT col_a1, col_a2, col_a3 FROM wp_term_taxonomy LEFT JOIN wp_terms ON (wp_term_taxonomy.term_id =
wp_terms.term_id) WHERE wp_term_taxonomy.taxonomy = 'product-category'";
$sql2 = "SELECT col_b1, col_b2, col_b3 FROM wp_posts WHERE (post_type = 'products' OR post_type = 'page')
AND (post_status = 'publish' OR post_status = 'suspended') AND ID NOT IN
(231, 236, 1070, 1245) order by post_title ASC";
$sql = $sql1." UNION ".$sql2;
$query = $sql . " limit " . $start . "," . $resultPerPage->perpage;
$list = $db_handle->runBackendQuery($query);

Related

NOT LIKE does not work with JOIN in wordpress

I have this sql query in wordpress with php
$sql = "SELECT last_update.post_id FROM {$wpdb->postmeta} last_update";
$sql .= " JOIN {$wpdb->posts} AS post ON last_update.post_id = post.ID";
$sql .= $wpdb->prepare(" WHERE {$time} - last_update.meta_value > {$ttl} AND last_update.meta_key = %s", Importer::META_LAST_UPDATE);
if (SyncConfig::getInstance()->option('published_only'))
$sql .= " AND post.post_status = 'publish'";
$sql .= $wpdb->prepare(" ORDER BY last_update.meta_value ASC LIMIT %d", self::getProductLimit());
$product_ids = $wpdb->get_col($sql);
shuffle($product_ids);
error_log(print_r( $product_ids, true ));
What I want is to skip the results with a "NOT LIKE" for the wildcard result "Product data not found"
Normally I would do something like this
$sql = "SELECT last_update.post_id FROM {$wpdb->postmeta} last_update";
$sql .= " JOIN {$wpdb->posts} AS post ON last_update.post_id = post.ID";
//QUITAR PRODUCTOS CON DATA NOT FOUND
$sql .= " JOIN {$wpdb->postmeta} AS _ety_product_info ON last_update.post_id = _ety_product_info.post_id";
$sql .= $wpdb->prepare(" WHERE {$time} - last_update.meta_value > {$ttl} AND last_update.meta_key = %s", Importer::META_LAST_UPDATE);
//QUITAR PRODUCTOS CON DATA NOT FOUND
$sql .= " AND _ety_product_info.meta_value NOT LIKE '%Product data not found%'";
if (SyncConfig::getInstance()->option('published_only'))
$sql .= " AND post.post_status = 'publish'";
$sql .= $wpdb->prepare(" ORDER BY last_update.meta_value ASC LIMIT %d", self::getProductLimit());
$product_ids = $wpdb->get_col($sql);
shuffle($product_ids);
error_log(print_r( $product_ids, true ));
But it gives wrong data.
The strangest thing is that if I remove the "NOT LIKE" and just leave it on "LIKE" it works delivering the expected result if the "_ety_product_info" column contains the value "Product data not found"
What am I doing wrong?
I want to exclude with "NOT LIKE" but it doesn't work.
Apparently this error only happens when I do the "JOIN"
Note: To identify the changes made in the original code with the edited one, just search for: //QUITAR PRODUCTOS CON DATA NOT FOUND
The final query
$sql it would be this:
SELECT last_update.post_id
FROM wp_postmeta last_update
JOIN wp_posts AS post ON last_update.post_id = post.ID
JOIN wp_postmeta AS _ety_product_info ON last_update.post_id = _ety_product_info.post_id
WHERE 1659698743 - last_update.meta_value > 86400
AND last_update.meta_key = '_ety_last_update'
AND _ety_product_info.meta_value NOT LIKE '%Product data not found%'
AND post.post_status = 'publish'
ORDER BY last_update.meta_value ASC LIMIT 17
I also tried this but it didn't work.
$wild = '%';
$find = 'Product data not found';
$like = $wild . $wpdb->esc_like( $find ) . $wild;
$sql .= $wpdb->prepare(" AND _ety_product_info.meta_value NOT LIKE %s", $like);
For what it's worth, the query you showed us says NOT LIKE 'Product data not found'. I guess you want it to say NOT LIKE '%Product data not found%' with the % wildcard characters.
And, try using LEFT JOIN and putting the NOT LIKE in your ON-condition. In general for readability with these key/value metadata tables it's a good idea to put the key selector in the ON condition. It doesn't matter to the logic for JOINs but it does for LEFT JOINs.
SELECT last_update.post_id
FROM wp_postmeta last_update
JOIN wp_posts AS post
ON last_update.post_id = post.ID
AND last_update.meta_key = '_ety_last_update'
LEFT JOIN wp_postmeta AS _ety_product_info
ON last_update.post_id = _ety_product_info.post_id
AND _ety_product_info.meta_value NOT LIKE '%Product data not found%'
WHERE 1659698743 - last_update.meta_value > 86400
AND post.post_status = 'publish'
ORDER BY last_update.meta_value ASC
LIMIT 17
This might work for you: JOIN suppresses the rows from the first table that don't match the second table, but LEFT JOIN keeps them.
This is guesswork. I don't know what other keys are in your metadata tables.

Comparison in PHP SELECT statement with multi-row array as comparing variable [duplicate]

This question already has an answer here:
What to do with mysqli problems? Errors like mysqli_fetch_array(): Argument #1 must be of type mysqli_result and such
(1 answer)
Closed last year.
I have a query to group by id, sum, and then rank. The issue is that the table contains all classes and doesn't have a column to define the class of each data.
Therefore, I have to use another table to get the id's that are in the same class as the id being ranked and then compare them.
Here is the code that I have already tried but results to errors:
$que = "SELECT * FROM registration WHERE CurrentClass = (SELECT CurrentClass FROM registration WHERE AdmNo = '$user_id')";
$statemen = $connect->prepare($que);
$statemen->execute();
$res = $statemen->fetchAll();
foreach($res as $rowww) {
$resu1 = mysqli_query($conn, "SELECT AdmNo, rank, total_score
FROM (SELECT * WHERE AdmNo = '".$rowww['AdmNo']."', IF(#marks=(#marks:=total_score), #auto, #auto:=#auto+1) AS rank
FROM (SELECT * FROM
(SELECT AdmNo, SUM(Score) AS total_score
FROM `{$examination}`,
(SELECT #auto:=0, #marks:=0) as init
GROUP BY AdmNo) sub ORDER BY total_score DESC)t) as result
WHERE AdmNo = '$user_id'");
$row1 = mysqli_fetch_assoc($resu1);
$sum = $row1['total_score'];
$position = $row1['rank'];
$totalMarks = round($sum, 2);
}
To my understanding, the error
Warning: mysqli_fetch_assoc() expects parameter 1 to be mysqli_result, bool given in E:\xampp\htdocs\user...
Is because of the multi-row returned in the first query and that's why I need help with how I can solve this problem.
The required result are that the AdmNo's selected from registration are the only one that should be used in ranking.
Try this:
$query = "SELECT AdmNo, rank, total_score FROM (
SELECT * WHERE AdmNo = '" . $rowww['AdmNo'] . "', IF(#marks=(#marks:=total_score), #auto, #auto:=#auto+1) AS rank FROM (
SELECT * FROM (
SELECT AdmNo, SUM(Score) AS total_score FROM `" . $examination . "`, (
SELECT #auto:=0, #marks:=0
) as init GROUP BY AdmNo
) sub ORDER BY total_score DESC
) t
) as result WHERE AdmNo = '" . $user_id . "'";
$resu1 = mysqli_query($conn, $query);

select to multiply tables for print mysqli_num_rows

Good evening all.
Is there one that will give me an example of how to make such a script here:
I try to make a while combining 2 different tables in my database to get correct mysqli_num_rows.
Like this:
$Querypris ("SELECT * FROM" wpd2_posts` where post_status = 'wc-failed' and select * From `wpd2_postmeta` where meta_key = '_ order_total' and meta_value> 300 ')
$Num_rowspris = mysqli_num_rows ($ query price);
So I want to get mysqli_num_rows from all those who are post_status = 'wc-completed' but also meta_value> 300
Hope you understand what I mean :)
Well, your php code will not work like this. At least variable names must be consistent.
You should use JOIN clause in your sql statement. I suppose, there is a column like "post_id" in both tables.
$query_price = "SELECT * FROM wpd2_posts JOIN wpd2_postmeta USING (post_id) WHERE post_status = 'wc-completed' AND meta_key = '_order_total' AND meta_value > 300";
$result = mysqli_query($connection, $query_price);
$number_of_rows = mysqli_num_rows($result);
UPDATE:
If names of the columns, referring to ID of the post, are different in those tables, for example "ID" in "wpd2_posts" and "post_id" in "wpd2_postmeta", then you should use a following query:
SELECT * FROM wpd2_posts p JOIN wpd2_postmeta pm
ON p.ID = pm.post_id
WHERE p.post_status = 'wc-completed'
AND pm.meta_key = '_order_total' AND pm.meta_value > 300
UPDATE: removed space from '_ order_total'. changed to '_order_total'
SELECT * FROM wpd2_posts,wpd2_postmeta where wpd2_posts.post_status = wc-completed and wpd2_postmeta.meta_key = _ order_total and wpd2_postmeta.meta_value > 300 and wpd2_posts.fk=wpd2_postmeta.fk
this thing might not work for not having foreign key
SELECT * FROM wpd2_posts CROSS JOIN wpd2_postmeta where wpd2_posts.post_status = wc-completed and wpd2_postmeta.meta_key = _ order_total and wpd2_postmeta.meta_value > 300
Its better to use foreign keys.
hope this will help
If your site is WordPress then use this:
global $wpdb;
$sql="SELECT * FROM wpd2_posts pt INNER JOIN wpd2_postmeta pmt ON pmt.post_id = pt.ID WHERE pt.post_status = 'wc-completed' AND pmt.meta_key = '_order_total' AND pmt.meta_value>300";
$results = $wpdb->get_results($sql, ARRAY_A );
$num_rowspris = count($results);
// OR ---------
$results = $wpdb->query($sql);
$num_rowspris = $results->num_rows;
else :
Note: $conn is your DB connection
$results = mysqli_query($conn, $sql);
$num_rowspris = mysqli_num_rows($results);

WordPress Subquery returns more than 1 row on SELECT

I am executing this query with core cron by custom Wordpress plugin:
// MAKE SQL CALL
$SQL = "SELECT ".$wpdb->prefix."postmeta.post_id FROM ".$wpdb->prefix."postmeta
INNER JOIN ".$wpdb->prefix."posts ON (".$wpdb->prefix."posts.ID = ".$wpdb->prefix."postmeta.post_id )
WHERE ".$wpdb->prefix."postmeta.meta_key = '".$core_admin_values['listing_expiration']['key']."'
AND ".$wpdb->prefix."posts.post_status = 'publish'
AND ".$wpdb->prefix."postmeta.post_id = (SELECT ".$wpdb->prefix."postmeta.post_id FROM ".$wpdb->prefix."postmeta WHERE ".$wpdb->prefix."postmeta.meta_key = 'listing_status' AND ".$wpdb->prefix."postmeta.meta_value != 1)
AND ".$wpdb->prefix."posts.post_type = '".$core_admin_values['listing_expiration']['taxonomy']."_type'
AND DATE(".$wpdb->prefix."postmeta.meta_value) < DATE(NOW())";
$expired_listings = (array)$wpdb->get_results($SQL);
But return this error:
FastCGI sent in stderr: "PHP message: Database error of WordPress Subquery returns more than 1 row for SELECT
How to solve this? I tried some solutions by similar problems here in Stack, but it still fails.
For the sake of legibility I reformatted your query.
SELECT
postmeta.post_id
FROM
postmeta
INNER JOIN posts
ON (posts.ID = postmeta.post_id )
WHERE
postmeta.meta_key = '".$core_admin_values['listing_expiration']['key']."'
AND posts.post_status = 'publish'
AND postmeta.post_id =
(
SELECT
postmeta.post_id
FROM
postmeta
WHERE
postmeta.meta_key = 'listing_status'
AND postmeta.meta_value != 1
)
AND posts.post_type = '".$core_admin_values['listing_expiration']['taxonomy']."_type'
AND DATE(postmeta.meta_value) < DATE(NOW())";
I suspect your issue stems from the subquery in your where clause.
SELECT
postmeta.post_id
FROM
postmeta
WHERE
postmeta.meta_key = 'listing_status'
AND postmeta.meta_value != 1
And that this chunk is returning more than one result. If you want to match against more than one result, change from "=" to "in" like so:
AND postmeta.post_id in
(
SELECT
postmeta.post_id ...
)
try to add LIMIT on subquery
// MAKE SQL CALL
$SQL = "SELECT ".$wpdb->prefix."postmeta.post_id FROM ".$wpdb->prefix."postmeta
INNER JOIN ".$wpdb->prefix."posts ON (".$wpdb->prefix."posts.ID = ".$wpdb->prefix."postmeta.post_id )
WHERE ".$wpdb->prefix."postmeta.meta_key = '".$core_admin_values['listing_expiration']['key']."'
AND ".$wpdb->prefix."posts.post_status = 'publish'
AND ".$wpdb->prefix."postmeta.post_id = (SELECT ".$wpdb->prefix."postmeta.post_id FROM ".$wpdb->prefix."postmeta WHERE ".$wpdb->prefix."postmeta.meta_key = 'listing_status' AND ".$wpdb->prefix."postmeta.meta_value != 1 LIMIT 1)
AND ".$wpdb->prefix."posts.post_type = '".$core_admin_values['listing_expiration']['taxonomy']."_type'
AND DATE(".$wpdb->prefix."postmeta.meta_value) < DATE(NOW())";
$expired_listings = (array)$wpdb->get_results($SQL);
similar problem several years after, but, in my case, I wasn't able to find the query to make the change, so, I decided to remove the warning message (because it was just a warning) and the way that I used for did that was adding this lines to the wp-config.php file:
ini_set('display_errors','Off');
ini_set('error_reporting', E_ALL );
define('WP_DEBUG', false);
define('WP_DEBUG_DISPLAY', false);
Regards!

Merging these two database select queries

I wonder if there is a way of merging these two database queries so as to have one:
$result = $wpdb->get_row("SELECT meta_value FROM ".$wpdb->prefix.
"postmeta WHERE meta_key = '_cat_num' AND post_id = $var");
$name = $wpdb->get_row("SELECT name FROM ".AH_FEED_DETAILS_TABLE.
" WHERE id = " . (int)$result->meta_value);
return $name->name;
The first query finds the category value which is then used to find the name field in the AH_FEED_DETAILS_TABLE table
You can get the database to do the work for this by using the IN with a sub-query as follows:
$name = $wpdb->get_row("SELECT name FROM ".AH_FEED_DETAILS_TABLE.
" WHERE id IN (SELECT meta_value FROM ".$wpdb->prefix.
"postmeta WHERE meta_key = '_cat_num' AND post_id = $var)");
$result = $wpdb->get_row("SELECT name FROM ".$wpdb->prefix
.AH_FEED_DETAILS_TABLE." AS cat_tbl JOIN postmeta ON
cat_tbl.id=postmeta.meta_value
WHERE postmeta.meta_key = '_cat_num' AND postmeta.post_id = $var");
return $result->name;
I hope that helps giving the idea

Categories