I am looking to modify the default woocommerce Subscriptions by Product SQL query to only reflect the subscriptions product count for subscriptions that have a meta key = _schedule_next_payment and meta value within the next 7 days. The reason for this is I deliver product on a weekly basis and am trying to forecast all products that will likely be ordered in the next week.
I added the following query segment
LEFT JOIN (
SELECT *
FROM {$wpdb->posts} as subscriptionjk
INNER JOIN {$wpdb->postmeta} AS postmeta
ON subscriptionjk.id = postmeta.post_id
WHERE postmeta.meta_key = '_schedule_next_payment'
AND postmeta.meta_value BETWEEN '2020-09-07 00:00:00' AND '2020-09-14 00:00:00'
inside the default woocommerce query for class-wcs-report-subscriptions-by-product which generates the Subscriptions by Product report
"SELECT product.id as product_id,
product.post_parent as parent_product_id,
product.post_title as product_name,
mo.product_type,
COUNT(subscription_line_items.subscription_id) as subscription_count,
SUM(subscription_line_items.product_total) as recurring_total
FROM {$wpdb->posts} AS product
LEFT JOIN (
SELECT tr.object_id AS product_id, t.slug AS product_type
FROM {$wpdb->prefix}term_relationships AS tr
INNER JOIN {$wpdb->prefix}term_taxonomy AS x
ON ( x.taxonomy = 'product_type' AND x.term_taxonomy_id = tr.term_taxonomy_id )
INNER JOIN {$wpdb->prefix}terms AS t
ON t.term_id = x.term_id
) AS mo
ON product.id = mo.product_id
LEFT JOIN (
SELECT wcoitems.order_id as subscription_id, wcoimeta.meta_value as product_id, wcoimeta.order_item_id, wcoimeta2.meta_value as product_total
FROM {$wpdb->prefix}woocommerce_order_items AS wcoitems
INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS wcoimeta
ON wcoimeta.order_item_id = wcoitems.order_item_id
INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS wcoimeta2
ON wcoimeta2.order_item_id = wcoitems.order_item_id
WHERE wcoitems.order_item_type = 'line_item'
AND ( wcoimeta.meta_key = '_product_id' OR wcoimeta.meta_key = '_variation_id' )
AND wcoimeta2.meta_key = '_line_total'
) as subscription_line_items
ON product.id = subscription_line_items.product_id
LEFT JOIN (
SELECT *
FROM {$wpdb->posts} as subscriptionjk
INNER JOIN {$wpdb->postmeta} AS postmeta
ON subscriptionjk.id = postmeta.post_id
WHERE postmeta.meta_key = '_schedule_next_payment'
AND postmeta.meta_value BETWEEN '2020-09-07 00:00:00' AND '2020-09-14 00:00:00'
) as subscriptions
ON subscriptions.ID = subscription_line_items.subscription_id
WHERE product.post_status = 'publish'
AND ( product.post_type = 'product' OR product.post_type = 'product_variation' )
AND subscriptions.post_type = 'shop_subscription'
AND subscriptions.post_status NOT IN( 'wc-pending', 'trash' )
GROUP BY product.id
ORDER BY COUNT(subscription_line_items.subscription_id) DESC" );
With that function as is it works and delivers the results I am looking for. However I have tried replacing those hard coded dates with a BETWEEN function using guidance from this stack overflow question and with different configurations I am trying it delivers no results.
I have tried this:
AND postmeta.meta_value BETWEEN GETDATE() AND DATEADD(day, -7, GETDATE())
Here is the solution that worked:
LEFT JOIN (
SELECT *
FROM {$wpdb->posts} as subscriptionjk
INNER JOIN {$wpdb->postmeta} AS postmeta
ON subscriptionjk.id = postmeta.post_id
WHERE postmeta.meta_key = '_schedule_next_payment'
AND postmeta.meta_value BETWEEN CURDATE() AND (CURDATE() + INTERVAL 7 DAY)
) as subscriptions
ON subscriptions.ID = subscription_line_items.subscription_id
When importing products with WpAllImport, all of our products are stored as variable products, even if they don't have any variations. We need these to be stored as single products.
How can we change all the product type to single for all products that doesn't have any variations using MySql? We're having trouble with the query.
Hoping some WooCommerce experts can help us out with this one..
Thank you very much!
First from MySQL take back up of your database, then you can get id of your product type from below query:
select term_id from wp_terms where name='variable' // assume return 4 as result
select term_id from wp_terms where name='simple' // assume return 2 as result
By above query you can get id of both product type.which need to use in update query mentioned below.
UPDATE wp_term_relationships
INNER JOIN wp_terms ON (wp_term_relationships.term_taxonomy_id = wp_terms.term_id)
SET wp_term_relationships.term_taxonomy_id = '2' where wp_term_relationships.term_taxonomy_id = '4'
First get all variable products with a loop. Using each product post Id, get the available variations. If there are no variations for the product. Then change each to simple.
<?php
$args = array(
'post_type' => 'product',
'product_type' => 'variable'
);
$products = new WP_Query( $args );
if ( $products->have_posts() ) {
while ( $products->have_posts() ) : $products->the_post();
$variations = array();
$id = the_ID();
$args = array(
'post_parent' => $id
);
$variations = get_children( $args );
if(sizeOf($variations) == 0){
wp_set_object_terms( $id, 'simple', 'product_type' );
}
endwhile;
}
?>
-- update WooCommerce variable products without variations to simple
--1
CREATE TABLE PPCD_EDI_TEMP_UPDATE
SELECT r.object_id
FROM wp_posts wp
LEFT JOIN wp_term_relationships r ON wp.ID = r.object_id
LEFT JOIN wp_postmeta SKU on SKU.post_id = wp.ID and SKU.meta_key = '_sku' -- SKU.meta_value as sku
LEFT JOIN wp_postmeta PRICE on PRICE.post_id = wp.ID and PRICE.meta_key = '_price' -- PRICE.meta_value as price
LEFT JOIN wp_wc_product_custom_lookup PCL on PCL.product_id = wp.ID
LEFT JOIN wp_term_taxonomy tt ON r.term_taxonomy_id = tt.term_taxonomy_id
LEFT JOIN wp_terms t ON t.term_id = tt.term_id
LEFT JOIN wp_posts wpv ON wp.id = wpv.post_parent AND wpv.post_type != 'attachment'
WHERE tt.taxonomy = 'product_type'
AND t.name = 'variable'
and wpv.ID is null; --test for one product, replace ; with the following: and SKU.meta_value = '10001894';
--2
UPDATE wp_term_relationships
SET term_taxonomy_id = (select term_id from wp_terms where name='simple')
WHERE term_taxonomy_id = (select term_id from wp_terms where name='variable') AND object_id IN (select object_id from PPCD_EDI_TEMP_UPDATE);
--test
SELECT SKU.meta_value as sku, PRICE.meta_value as price,
wp.id AS 'Product Id',
wpv.id AS 'Variant Id',
wp.post_title as parent_title,
wpv.post_title as variant_title,
wpv.post_excerpt
FROM wp_posts wp
LEFT JOIN wp_term_relationships r ON wp.ID = r.object_id
LEFT JOIN wp_postmeta SKU on SKU.post_id = wp.ID and SKU.meta_key = '_sku' -- SKU.meta_value as sku
LEFT JOIN wp_postmeta PRICE on PRICE.post_id = wp.ID and PRICE.meta_key = '_price' -- PRICE.meta_value as price
LEFT JOIN wp_wc_product_custom_lookup PCL on PCL.product_id = wp.ID
LEFT JOIN wp_term_taxonomy tt ON r.term_taxonomy_id = tt.term_taxonomy_id
LEFT JOIN wp_terms t ON t.term_id = tt.term_id
LEFT JOIN wp_posts wpv ON wp.id = wpv.post_parent AND wpv.post_type != 'attachment'
WHERE tt.taxonomy = 'product_type'
AND t.name = 'variable'
and wpv.ID is null;
I have the following query that I'm working on for a wordpress website:
Select
posts_tender.ID AS tender_ID,
tender_meta_user_ministry_tbl.meta_value,
CONCAT('<a style="font-weight: bold;font-size: 15px;" href="'
,posts_tender.guid
,'" target="_blank">المزيد...</a>') AS tender_title_with_link_to_post,
posts_tender.post_status AS tender_post_status,
DATE_FORMAT(STR_TO_DATE(tender_meta_tender_date_tbl.meta_value , '%Y-%m-%dT%H:%i'), '%d/%m/%Y') AS tender_meta_tender_date,
posts_tender.post_title AS tender_meta_tender_subject,
tender_taxonomy_language_tbl.name AS tender_taxonomy_language,
tender_taxonomy_tendercategory_tbl.name AS tender_taxonomy_tendercategory,
tender_meta_tender_status_tbl.meta_value AS tender_meta_tender_status
FROM wp_posts AS posts_tender
LEFT OUTER JOIN
(SELECT tender_meta_tender_date_tbl_posts.ID as id,
meta_value,
meta_key
FROM wp_postmeta AS tender_meta_tender_date_tbl_postmeta
INNER JOIN wp_posts AS tender_meta_tender_date_tbl_posts
ON tender_meta_tender_date_tbl_postmeta.post_id = tender_meta_tender_date_tbl_posts.ID
AND tender_meta_tender_date_tbl_posts.post_type = 'tender'
) AS tender_meta_tender_date_tbl
ON tender_meta_tender_date_tbl.meta_key = 'tender_date'
AND tender_meta_tender_date_tbl.id = posts_tender.ID
LEFT OUTER JOIN
(SELECT tender_meta_user_ministry_tbl_posts.ID as id,
meta_value,
meta_key
FROM wp_postmeta AS tender_meta_user_ministry_tbl_postmeta
INNER JOIN wp_posts AS tender_meta_user_ministry_tbl_posts
ON tender_meta_user_ministry_tbl_postmeta.post_id = tender_meta_user_ministry_tbl_posts.ID
AND tender_meta_user_ministry_tbl_posts.post_type = 'tender'
) AS tender_meta_user_ministry_tbl
ON tender_meta_user_ministry_tbl.meta_key = 'user_ministry'
AND tender_meta_user_ministry_tbl.id = posts_tender.ID
LEFT OUTER JOIN
(SELECT name,
object_id as id
FROM wp_terms AS tender_taxonomy_language_tbl_terms
INNER JOIN wp_term_taxonomy AS tender_taxonomy_language_tbl_termtaxonomy
ON tender_taxonomy_language_tbl_termtaxonomy.term_id = tender_taxonomy_language_tbl_terms.term_id
AND tender_taxonomy_language_tbl_termtaxonomy.taxonomy = 'language'
INNER JOIN wp_term_relationships AS rel_tender_taxonomy_language_tbl
ON tender_taxonomy_language_tbl_termtaxonomy.term_taxonomy_id = rel_tender_taxonomy_language_tbl.term_taxonomy_id
) AS tender_taxonomy_language_tbl
ON tender_taxonomy_language_tbl.ID = posts_tender.id
LEFT OUTER JOIN
(SELECT name,
object_id as id,
tender_taxonomy_tendercategory_tbl_terms.term_id AS tender_category_id
FROM wp_terms AS tender_taxonomy_tendercategory_tbl_terms
INNER JOIN wp_term_taxonomy AS tender_taxonomy_tendercategory_tbl_termtaxonomy
ON tender_taxonomy_tendercategory_tbl_termtaxonomy.term_id = tender_taxonomy_tendercategory_tbl_terms.term_id
AND tender_taxonomy_tendercategory_tbl_termtaxonomy.taxonomy = 'tendercategory'
INNER JOIN wp_term_relationships AS rel_tender_taxonomy_tendercategory_tbl
ON tender_taxonomy_tendercategory_tbl_termtaxonomy.term_taxonomy_id = rel_tender_taxonomy_tendercategory_tbl.term_taxonomy_id
) AS tender_taxonomy_tendercategory_tbl
ON tender_taxonomy_tendercategory_tbl.ID = posts_tender.id
LEFT OUTER JOIN
(SELECT tender_meta_tender_status_tbl_posts.ID as id,
meta_value,
meta_key
FROM wp_postmeta AS tender_meta_tender_status_tbl_postmeta
INNER JOIN wp_posts AS tender_meta_tender_status_tbl_posts
ON tender_meta_tender_status_tbl_postmeta.post_id = tender_meta_tender_status_tbl_posts.ID
AND tender_meta_tender_status_tbl_posts.post_type = 'tender'
) AS tender_meta_tender_status_tbl
ON tender_meta_tender_status_tbl.meta_key = 'tender_status'
AND tender_meta_tender_status_tbl.id = posts_tender.ID
where 1=1
AND posts_tender.post_type = 'tender'
And posts_tender.post_status = 'publish'
And tender_taxonomy_language_tbl.name = 'العربية'
And (tender_meta_tender_status_tbl.meta_value is NULL
OR tender_meta_tender_status_tbl.meta_value = 0)
And SUBSTRING_INDEX(
SUBSTRING_INDEX(
tender_meta_user_ministry_tbl.meta_value,
'\"',
-2),
'\"',
1) = Case
When (1103 = 0 Or 1103 = '' Or 1103= null Or 1103= 'null')
then 0
else 1103
End
and the query is working fine on my local database, but after importing the database on a live environment, the query is returning no data.
After troubleshooting the issue, if I added the below where condition to the query, a record will return:
and posts_tender.ID =14261
Does anyone have an idea on why is this happening?
I run this query to get 20 random items from my wordpress database based on things like rating, category, etc
SELECT (A.user_votes/A.user_voters) as site_rating, B.ID as post_id, B.post_author, B.post_date,E.name as category
FROM `wp_gdsr_data_article` as A
INNER JOIN `wp_posts` as B ON (A.post_id = B.id)
INNER JOIN wp_term_relationships C ON (B.ID = C.object_id)
INNER JOIN wp_term_taxonomy D ON (C.term_taxonomy_id = D.term_taxonomy_id)
INNER JOIN wp_terms E ON (D.term_id = E.term_id)
WHERE
B.post_type = 'post' AND
B.post_status = 'publish' AND
D.taxonomy='category' AND
E.name NOT IN ('Satire', 'Declined', 'Outfits','Unorganized', 'AP')
ORDER BY RAND()
LIMIT 20
Then, for each result of the random items, I want to find a corresponding item that is very similar to the random item (around the same rating) but not identical and also one the user has not seen:
SELECT ABS($site_rating-(A.user_votes/A.user_voters)) as diff, (A.user_votes/A.user_voters) as site_rating, B.ID as post_id, B.post_author, B.post_date,E.name as category ,IFNULL(F.count,0) as count
FROM `wp_gdsr_data_article` as A
INNER JOIN `wp_posts` as B ON (A.post_id = B.id)
INNER JOIN wp_term_relationships C ON (B.ID = C.object_id)
INNER JOIN wp_term_taxonomy D ON (C.term_taxonomy_id = D.term_taxonomy_id)
INNER JOIN wp_terms E ON (D.term_id = E.term_id)
LEFT JOIN (
SELECT *,COUNT(*) as count FROM `verus` WHERE ip = '{$_SERVER['REMOTE_ADDR']}'
) as F ON (A.post_id = F.post_id_winner OR A.post_id = F.post_id_loser)
WHERE
E.name = '$category' AND
B.ID <> '$post_id' AND
B.post_type = 'post' AND
B.post_status = 'publish' AND
D.taxonomy='category' AND
E.name NOT IN ('Satire', 'Declined', 'Outfits','Unorganized', 'AP')
ORDER BY count ASC, diff ASC
LIMIT 1
Where the following php variables refer to the result of the previous query
$post_id = $result['post_id'];
$category = $result['category'];
$site_rating = $result['site_rating'];
and $_SERVER['REMOTE_ADDR'] refers to the user's IP.
Is there a way to combine the first query with the 20 additional queries that need to be called to find corresponding items, so that I need just 1 or 2 queries?
Edit: Here is the view that simplifies the joins
CREATE VIEW `versus_random` AS
SELECT (A.user_votes/A.user_voters) as site_rating, B.ID as post_id, B.post_author, B.post_date,E.name as category
FROM `wp_gdsr_data_article` as A
INNER JOIN `wp_posts` as B ON (A.post_id = B.id)
INNER JOIN wp_term_relationships C ON (B.ID = C.object_id)
INNER JOIN wp_term_taxonomy D ON (C.term_taxonomy_id = D.term_taxonomy_id)
INNER JOIN wp_terms E ON (D.term_id = E.term_id)
WHERE
B.post_type = 'post' AND
B.post_status = 'publish' AND
D.taxonomy='category' AND
E.name NOT IN ('Satire', 'Declined', 'Outfits','Unorganized', 'AP')
My attempt now with the view:
SELECT post_id,
(
SELECT INNER_TABLE.post_id
FROM `versus_random` as INNER_TABLE
WHERE
INNER_TABLE.post_id <> OUTER_TABLE.post_id
ORDER BY (SELECT COUNT(*) FROM `versus` WHERE ip = '54' AND (INNER_TABLE.post_id = post_id_winner OR INNER_TABLE.post_id = post_id_loser)) ASC
LIMIT 1
) as innerquery
FROM `versus_random` as OUTER_TABLE
ORDER BY RAND()
LIMIT 20
However the query just timesout and freezes my mysql.
I think it should work like this, but I don't have any Wordpress at hand to test it. The second query that gets the related post is embedded in the other query, when it gets just the related_post_id. The whole query is turned into a subquery itself, given the alias 'X' (although you are free to use 'G', if you want to continue your alphabet.)
In the outer query, the tables for posts and data-article are joined again (RA and RP) to query the relevant fields of the related post, based on the related_post_id from the inner query. These two tables are left joined (and in reverse order), so you still get the main post if no related post was found.
SELECT
X.site_rating,
X.post_id,
X.post_author,
X.post_date,
X.category,
RA.user_votes / RA.user_voters as related_post_site_rating,
RP.ID as related_post_id,
RP.post_author as related_post_author,
RP.post_date as related_post_date,
RP.name as related_category,
FROM
( SELECT
(A.user_votes/A.user_voters) as site_rating,
B.ID as post_id, B.post_author, B.post_date,E.name as category,
( SELECT
RB.ID as post_id
FROM `wp_gdsr_data_article` as RA
INNER JOIN `wp_posts` as RB ON (RA.post_id = RB.id)
INNER JOIN wp_term_relationships RC ON (RB.ID = RC.object_id)
INNER JOIN wp_term_taxonomy RD ON (RC.term_taxonomy_id = RD.term_taxonomy_id)
INNER JOIN wp_terms RE ON (RD.term_id = RE.term_id)
LEFT JOIN (
SELECT *,COUNT(*) as count FROM `verus` WHERE ip = '{$_SERVER['REMOTE_ADDR']}'
) as RF ON (RA.post_id = RF.post_id_winner OR RA.post_id = RF.post_id_loser)
WHERE
RE.name = E.name AND
RB.ID <> B.ID AND
RB.post_type = 'post' AND
RB.post_status = 'publish' AND
RD.taxonomy='category' AND
RE.name NOT IN ('Satire', 'Declined', 'Outfits','Unorganized', 'AP')
ORDER BY count ASC, diff ASC
LIMIT 1) as related_post_id
FROM `wp_gdsr_data_article` as A
INNER JOIN `wp_posts` as B ON (A.post_id = B.id)
INNER JOIN wp_term_relationships C ON (B.ID = C.object_id)
INNER JOIN wp_term_taxonomy D ON (C.term_taxonomy_id = D.term_taxonomy_id)
INNER JOIN wp_terms E ON (D.term_id = E.term_id)
WHERE
B.post_type = 'post' AND
B.post_status = 'publish' AND
D.taxonomy='category' AND
E.name NOT IN ('Satire', 'Declined', 'Outfits','Unorganized', 'AP')
ORDER BY RAND()
LIMIT 20
) X
LEFT JOIN `wp_posts` as RP ON RP.id = X.related_post_id
LEFT JOIN `wp_gdsr_data_article` as RA.post_id = RP.id
I can't test my proposal so take it with the benefit of the doubt. Anyway i hope it could be a valid starting point for some of the issues faced.
I can not imagine a solution that does not pass through a temporary table, cabling onerous computations present in your queries. You could also have the goal to not interfere with the randomization of the first phase. In the following I try to clarify.
I'll start with these rewritings:
-- first query
SELECT site_rating, post_id, post_author, post_date, category
FROM POSTS_COMMON
ORDER BY RAND()
LIMIT 20
-- second query
SELECT ABS(R.site_rating_A - R.site_rating_B) as diff, R.site_rating_B as site_rating, P.post_id, P.post_author, P.post_date, P.category, F.count
FROM POSTS_COMMON AS P
INNER JOIN POSTS_RATING_DIFFS AS R ON (P.post_id = R.post_id_B)
LEFT JOIN (
/* post_id_winner, post_id_loser explicited; COUNT(*) NULL treatment anticipated */
SELECT post_id_winner, post_id_loser, IFNULL(COUNT(*), 0) as count FROM `verus` WHERE ip = '{$_SERVER['REMOTE_ADDR']}'
) as F ON (P.post_id = F.post_id_winner OR P.post_id = F.post_id_loser)
WHERE
P.category = '$category'
AND R.post_id_A = '$post_id'
ORDER BY count ASC, diff ASC
LIMIT 1
with:
SELECT A.post_id_A, B.post_id_B, A.site_rating as site_rating_A, B.site_rating as site_rating_B
INTO POSTS_RATING_DIFFS
FROM POSTS_COMMON as A, POSTS_COMMON as B
WHERE A.post_id <> B.post_id AND A.category = B.category
CREATE VIEW POSTS_COMMON AS
SELECT A.ID as post_id, A.user_votes, A.user_voters, (A.user_votes / A.user_voters) as site_rating, B.post_author, B.post_date, E.name as category
FROM wp_gdsr_data_article` as A
INNER JOIN `wp_posts` as B ON (A.post_id = B.post_id)
INNER JOIN wp_term_relationships C ON (B.ID = C.object_id)
INNER JOIN wp_term_taxonomy D ON (C.term_taxonomy_id = D.term_taxonomy_id)
INNER JOIN wp_terms E ON (D.term_id = E.term_id)
WHERE
B.post_type = 'post' AND
B.post_status = 'publish' AND
D.taxonomy='category' AND
E.name NOT IN ('Satire', 'Declined', 'Outfits','Unorganized', 'AP')
POSTS_COMMON isolates a common view between the two queries.
With POSTS_RATING_DIFFS, a temporary table populated with the ratings combinations and diffs, we have "the trick" of transforming the inequality join criteria on post_id(s) in an equality one (see R.post_id_A = '$post_id' in the second query).
We also take advantage of a temporary table in having precomputed ratings for the combinatory explosion of A.post_id <> B.post_id (with post category equality), and moreover being useful for other sessions.
Also extracting the RAND() ordering in a temporary table could be advantageous. In this case we could limit the ratings combinations and diffs only on the 20 randomly chosen.
Original limiting to one single row in the dependent second level query is done by mean of ordering and limit statements.
The proposed solution avoids elaborating a LIMIT 1 on an ORDER BY resultset in the second level query wich become a subquery.
The single row calculation in the subquery is done by mean of a WHERE criteria on the maximum of a single value calculated from the columns values on which ORDER BY clause is used.
The combination into a single value must be valid in preserving the correct ordering. I'll leave in pseudo-code as:
'<combination of count and diff>'
For example, using combination of the two values into a string type, we could have:
CONCAT(LPAD(CAST(count AS CHAR), 10, '0'), LPAD(CAST(ABS(diff) AS CHAR), 20, '0'))
The structure of the single query would be:
SELECT (Q_LVL_1.user_votes/Q_LVL_1.user_voters) as site_rating_LVL_1, Q_LVL_1.post_id as post_id_LVL_1
, Q_LVL_1.post_author as post_author_LVL_1, Q_LVL_1.post_date as post_date_LVL_1
, Q_LVL_1.category as category_LVL_1, Q_LVL_2.post_id as post_id_LVL_2
, Q_LVL_2.diff as diff_LVL_2, Q_LVL_2.site_rating as site_rating_LVL_2
, Q_LVL_2.post_author as post_author_LVL_2, Q_LVL_2.post_date as post_date_LVL_2
, Q_LVL_2.count
FROM POSTS_COMMON AS Q_LVL_1
, /* 1-row-selection query placed side by side for each Q_LVL_1's row */
(
SELECT CORE_P.post_id, CORE_P.ABS_diff as diff, P.site_rating, P.post_author, P.post_date, CORE_P.count
FROM POSTS_COMMON AS P
INNER JOIN (
SELECT FIRST(CORE_P.post_id) as post_id, ABS(CORE_P.diff) as ABS_diff, CORE_P.count
FROM (
/*
selection of posts with post_id(s) different from first level query,
not already taken and with the topmost value of
'<combination of count and diff>'
*/
) AS CORE_P
GROUP BY CORE_P.count, ABS(CORE_P.diff)
/* the one row selector */
) AS CORE_ONE_LINER ON P.post_id = CORE_ONE_LINER.post_id
) AS Q_LVL_2
ORDER BY RAND()
LIMIT 20
CORE_P selection could have more post_id(s) corresponding to the topmost value '<combination of count and diff>', so the use of GROUP BY and FIRST clauses to reach the single row.
This brings to a possible final implementation:
SELECT (Q_LVL_1.user_votes/Q_LVL_1.user_voters) as site_rating_LVL_1, Q_LVL_1.post_id as post_id_LVL_1
, Q_LVL_1.post_author as post_author_LVL_1, Q_LVL_1.post_date as post_date_LVL_1
, Q_LVL_1.category as category_LVL_1, Q_LVL_2.post_id as post_id_LVL_2
, Q_LVL_2.diff as diff_LVL_2, Q_LVL_2.site_rating as site_rating_LVL_2
, Q_LVL_2.post_author as post_author_LVL_2, Q_LVL_2.post_date as post_date_LVL_2
, Q_LVL_2.count
FROM POSTS_COMMON AS Q_LVL_1
, (
SELECT CORE_P.post_id, CORE_P.ABS_diff as diff, P.site_rating, P.post_author, P.post_date, CORE_P.count
FROM POSTS_COMMON AS P
INNER JOIN
(
SELECT FIRST(CORE_P.post_id) as post_id, ABS(CORE_P.diff) as ABS_diff, CORE_F.count
FROM (
SELECT CORE_RATING.post_id as post_id, ABS(CORE_RATING.diff) as ABS_diff, CORE_F.count
FROM (
SELECT post_id_B as post_id, site_rating_A - site_rating_B as diff
FROM POSTS_RATING_DIFFS
WHERE POSTS_RATING_DIFFS.post_id_A = Q_LVL_1.post_id
) as CORE_RATING
LEFT JOIN (
SELECT post_id_winner, post_id_loser, IFNULL(COUNT(*), 0) as count
FROM `verus`
WHERE ip = '{$_SERVER['REMOTE_ADDR']}'
) as CORE_F ON (CORE_RATING.post_id = CORE_F.post_id_winner OR CORE_RATING.post_id = CORE_F.post_id_loser)
WHERE
POSTS_RATING_DIFFS.post_id_A = Q_LVL_1.post_id
AND '<combination of CORE_F.count and CORE_RATING.diff>'
= MAX (
SELECT '<combination of CORE_F_2.count and CORE_RATING_2.diff>'
FROM (
SELECT site_rating_A - site_rating_B as diff
FROM POSTS_RATING_DIFFS
WHERE POSTS_RATING_DIFFS.post_id_A = Q_LVL_1.post_id
) as CORE_RATING_2
LEFT JOIN (
SELECT post_id_winner, post_id_loser, IFNULL(COUNT(*), 0) as count
FROM `verus`
WHERE ip = '{$_SERVER['REMOTE_ADDR']}'
) as CORE_F_2 ON (CORE_RATING_2.post_id = CORE_F_2.post_id_winner OR CORE_RATING_2.post_id = CORE_F_2.post_id_loser)
) /* END MAX */
) AS CORE_P
GROUP BY CORE_P.count, ABS(CORE_P.diff)
) AS CORE_ONE_LINER ON P.post_id = CORE_ONE_LINER.post_id
) AS Q_LVL_2
ORDER BY RAND()
LIMIT 20