I have a mysql query something like this.
SELECT SQL_CALC_FOUND_ROWS wp_posts . * , wp_geodir_gd_place_detail . *
FROM wp_posts
INNER JOIN wp_geodir_gd_place_detail ON ( wp_geodir_gd_place_detail.post_id = wp_posts.ID )
INNER JOIN wp_term_relationships ON ( wp_posts.ID = wp_term_relationships.object_id )
WHERE 1 =1
AND (
wp_posts.post_status = 'publish'
OR wp_posts.post_status = 'private'
)
AND wp_posts.post_type = 'gd_place'
AND (
wp_term_relationships.term_taxonomy_id
IN ( 2, 6, 8 )
)
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_title ASC , wp_posts.post_title ASC
But its returning full rows with details. Can someone help me to get the count of affected rows instead of full rows?
Related
I have a wordpress installation with a large amount of entries (posts) in the table.
I have the following query that is taking almost 30 seconds. Any ideas on how I can optimize?
I think that the cast is what is stalling here but not sure.
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
INNER JOIN wp_postmeta
ON ( wp_posts.ID = wp_postmeta.post_id )
INNER JOIN wp_postmeta AS mt1
ON ( wp_posts.ID = mt1.post_id )
WHERE 1=1
AND ( wp_postmeta.meta_key = 'post_views_count_7_day_total'
AND ( mt1.meta_key = 'post_views_count_7_day_last_date'
AND CAST(mt1.meta_value AS SIGNED) > '1626290358' ) )
AND wp_posts.post_type = 'post'
AND ((wp_posts.post_status = 'publish'))
GROUP BY wp_posts.ID
ORDER BY CAST(wp_postmeta.meta_value AS SIGNED) DESC
LIMIT 0, 3
In a WordPress installation, I need to order products so that:
Sold products show up last.
Sold products tagged "antique" show up after sold products tagged "reproduction."
I have successfully completed the first item, but I am at a loss regarding the second item. I'm not getting any errors. My problem is that everything in my ORDER BY statement is working except for "wt.slug DESC." If I change the LEFT JOIN statements for wp_term_taxonomy and wp_terms tables to INNER JOIN statements, I get 0 results, so it looks to me like these statements are not finding the results that I expect. Here is my query:
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
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 )
LEFT JOIN wp_postmeta stock ON ( wp_posts.ID = stock.post_id AND stock.meta_key = '_stock_status' )
LEFT JOIN wp_term_taxonomy wtt ON ( wp_term_relationships.term_taxonomy_id = wtt.term_taxonomy_id AND wtt.taxonomy = 'product_tag' )
LEFT JOIN wp_terms wt ON ( wtt.term_id = wt.term_id AND ( wt.slug = 'antique' OR wt.slug = 'reproduction' ) )
WHERE 1=1
AND ( wp_term_relationships.term_taxonomy_id IN (171) )
AND ( ( wp_postmeta.meta_key = '_visibility' AND CAST(wp_postmeta.meta_value AS CHAR) IN ('visible','catalog') ) )
AND wp_posts.post_type = 'product'
AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_type DESC, stock.meta_value ASC, wt.slug DESC, wp_posts.post_date
Here is the WordPress database description for reference. I would appreciate any assistance.
You can create a new field as
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID, CASE wt.slug WHEN 'antique' THEN -1 WHEN 'reproduction' THEN 0 ELSE 1 END as sort_order
and use the sort_order in ORDER BY clause like
ORDER BY sort_order DESC
Thanks to help from #mynawaz, I have been able to come up with a solution. I'm not sure if it's the most efficient or elegant solution, but it works:
SELECT SQL_CALC_FOUND_ROWS wp_posts.* , CASE wt.slug WHEN 'antique' THEN 1 WHEN 'reproduction' THEN 2 ELSE 0 END as slug_order
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 )
LEFT JOIN wp_postmeta stock ON ( wp_posts.ID = stock.post_id AND stock.meta_key = '_stock_status' )
LEFT JOIN wp_term_relationships wtr ON ( wp_posts.ID = wtr.object_id AND stock.meta_value = 'outofstock' )
LEFT JOIN wp_term_taxonomy wtt ON ( wtr.term_taxonomy_id = wtt.term_taxonomy_id AND wtt.taxonomy = 'product_tag' )
LEFT JOIN wp_terms wt ON ( wtt.term_id = wt.term_id AND wt.slug IN( 'antique','reproduction' ) )
WHERE 1=1
AND ( wp_term_relationships.term_taxonomy_id IN (171) )
AND ( ( wp_postmeta.meta_key = '_visibility' AND CAST(wp_postmeta.meta_value AS CHAR) IN ('visible','catalog') ) )
AND wp_posts.post_type = 'product'
AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')
AND NOT (
stock.meta_value = 'outofstock'
AND ( CASE wt.slug WHEN 'antique' THEN 1 WHEN 'reproduction' THEN 2 ELSE 0 END ) = 0
)
GROUP BY wp_posts.ID, slug_order
ORDER BY wp_posts.post_type DESC, stock.meta_value ASC, slug_order DESC, wp_posts.post_date DESC
I'm querying the WordPress wp_postmeta table for the lowest meta_value of rows with the meta_key item_thickness:
SELECT min(cast(meta_value as unsigned)) FROM wp_postmeta WHERE meta_key='item_thickness'
This works great.
Question: How would I extend this query to select the same lowest item_thickness from rows with the same post_id and with meta_key='item_status' and meta_value='Raw'
The post_id forms the relationship between these rows but I don't know how to do a JOIN on the same table or the proper syntax for a sub-query
This is my latest (failing) attempt at the query:
SELECT *
FROM wp_postmeta
JOIN (
SELECT min(cast(meta_value as unsigned)), post_id FROM wp_postmeta WHERE meta_key='item_thickness'
) b
ON wp_postmeta.post_id=b.post_id
I was able to use WP_Query to build the MySQL I needed and then edit it so it would select the value I wanted.
Working query.
$wpdb->get_var( "SELECT min(cast(wp_postmeta.meta_value as unsigned)) FROM wp_postmeta INNER JOIN wp_posts ON ( wp_posts.ID = wp_postmeta.post_id ) INNER JOIN wp_postmeta AS mt1 ON ( wp_posts.ID = mt1.post_id ) WHERE 1=1 AND ( wp_postmeta.meta_key = 'item_thickness' AND ( mt1.meta_key = 'item_status' AND CAST(mt1.meta_value AS CHAR) = 'raw' )) AND wp_posts.post_type = 'inventory' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'future' OR wp_posts.post_status = 'draft' OR wp_posts.post_status = 'pending' OR wp_posts.post_status = 'private')" );
Hi there so i have this problem in the following query, inside wp_wti_like_post i have number of rows with similar post_id and with value column as 1 or -1.
So let's say for post with id 727 i have only one row , so the sum should be 1, but don't know why it does return 4 and when there are two rows with 727 it does return 8 query is below:
SELECT wp_posts. * ,
SUM( wp_wti_like_post.value ) -4 AS total_sum,
wp_wti_like_post.post_id
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 )
JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id )
LEFT JOIN wp_wti_like_post ON ( wp_posts.ID = wp_wti_like_post.post_id )
WHERE wp_term_taxonomy.taxonomy = 'category'
AND wp_term_taxonomy.term_id IN ('$c_cid')
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish')
GROUP BY wp_posts.ID
HAVING SUM( wp_wti_like_post.value ) > $min_like
ORDER BY wp_posts.post_date DESC
You are using joins among many tables and there may b a chance that any of them has many associations for a post_id therefore your sum is incorrect i suggest you to use a sub select for your like table and calculate sum in sub select and then join with your main query
SELECT
p.*, COALESCE(l.sum_like,0) AS total_sum,
l.post_id
FROM
wp_posts p
INNER JOIN wp_term_relationships ttr
ON (p.ID = ttr.object_id)
INNER JOIN wp_term_taxonomy tt
ON (ttr.term_taxonomy_id = tt.term_taxonomy_id)
LEFT JOIN (
SELECT post_id ,SUM(`value`) sum_like
FROM wp_wti_like_post
GROUP BY post_id
) l ON (p.ID = l.post_id)
WHERE tt.taxonomy = 'category'
AND tt.term_id IN ('21')
AND p.post_type = 'post'
AND (p.post_status = 'publish')
HAVING total_sum > 2
ORDER BY p.post_date DESC
Also note i have removed wp_postmeta join because its not used in your selection criteria and neither in your filter criteria also wp_postmeta stores different attributes for each post so i guess this table is producing more rows thats why wrong sum is calculated.
Removed -4 from query
I'm still pretty new to SQL, and I'm having trouble wrapping my mind around why one of these queries functions properly and one does not. This is stemming from my attempts to optimize a complex and slow query. #kalengi suggested what looks like a brilliant solution to me, but it doesn't seem to work on my site. Here are the queries.
This is the standard SQL that WordPress generates (this is working as expected):
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id)
INNER JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id)
WHERE 1=1
AND wp_posts.post_type = 'product'
AND (wp_posts.post_status = 'publish')
AND (
(wp_postmeta.meta_key = '_visibility' AND CAST(wp_postmeta.meta_value AS CHAR) IN ('visible','catalog'))
AND (mt1.meta_key = '_stock_status' AND CAST(mt1.meta_value AS CHAR) = 'instock')
)
GROUP BY wp_posts.ID
ORDER BY wp_posts.menu_order,wp_posts.post_title asc
LIMIT 0, 10
This is the SQL after #kalengi's filter processes it to combine the multiple INNER JOINs into one (this returns 0 results):
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
INNER JOIN wp_postmeta AS pmta ON (wp_posts.ID = pmta.post_id)
WHERE 1=1
AND wp_posts.post_type = 'product'
AND ( wp_posts.post_status = 'publish' )
AND (
( pmta.meta_key = '_visibility' AND CAST(pmta.meta_value AS CHAR) IN ( 'visible','catalog' ) )
AND ( pmta.meta_key = '_stock_status' AND CAST(pmta.meta_value AS CHAR) = 'instock' )
)
GROUP BY wp_posts.ID
ORDER BY wp_posts.menu_order,wp_posts.post_title asc
LIMIT 0, 10
Can anyone explain whey the second one doesn't work to me?
The two inner joins:
INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id)
INNER JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id)
represent two data sets (that happen to be "the same").
Given the WHERE condition, the results will be sets of two rows where the first (wp_postmeta) meets one condition:
(wp_postmeta.meta_key = '_visibility' AND CAST(wp_postmeta.meta_value AS CHAR) IN ('visible','catalog'))
And the second meets a completely different condition:
(mt1.meta_key = '_stock_status' AND CAST(mt1.meta_value AS CHAR) = 'instock')
By combining everything into one INNER JOIN, you're instead looking for ONE ROW which matches both conditions. Apparently there isn't one.
If you review the "brilliant solution", you'll see that 'AND's were changed to 'OR' to preserve the semantics:
AND (
( pmta.meta_key = '_visibility' AND CAST(pmta.meta_value AS CHAR) IN ( 'visible','catalog' ) )
OR ( pmta.meta_key = '_stock_status' AND CAST(pmta.meta_value AS CHAR) = 'instock' )
)
It looks like you have a condition in your WHERE clause that is looking for two values at the same time in the pmta.meta_key and pmta.meta_value columns:
....
( pmta.meta_key = '_visibility' AND CAST(pmta.meta_value AS CHAR) IN ('visible','catalog' ) )
AND ( pmta.meta_key = '_stock_status' AND CAST(pmta.meta_value AS CHAR) = 'instock' )
....
One column cannot have two different values in the same row, so this test will return FALSE, and consequently, no rows will be returned.
If you rewrite the original query to group the join conditions into the ON clauses, you can see why your second query won't work:
SELECT
SQL_CALC_FOUND_ROWS wp_posts.ID
FROM
wp_posts
INNER JOIN wp_postmeta
ON wp_posts.ID = wp_postmeta.post_id
AND wp_postmeta.meta_key = '_visibility'
AND CAST(wp_postmeta.meta_value AS CHAR) IN ('visible','catalog')
INNER JOIN wp_postmeta AS mt1
ON wp_posts.ID = mt1.post_id
AND mt1.meta_key = '_stock_status'
AND CAST(mt1.meta_value AS CHAR) = 'instock'
WHERE
1=1
AND wp_posts.post_type = 'product'
AND wp_posts.post_status = 'publish'
GROUP BY
wp_posts.ID
ORDER BY
wp_posts.menu_order,
wp_posts.post_title asc
LIMIT 0, 10
If you want to join the table only once, try something like this:
SELECT
SQL_CALC_FOUND_ROWS wp_posts.ID
FROM
wp_posts
INNER JOIN wp_postmeta
ON wp_posts.ID = wp_postmeta.post_id
AND (
wp_postmeta.meta_key = '_visibility'
AND CAST(wp_postmeta.meta_value AS CHAR) IN ('visible','catalog')
) OR (
wp_postmeta.meta_key = '_stock_status'
AND CAST(wp_postmeta.meta_value AS CHAR) = 'instock'
)
WHERE
1=1
AND wp_posts.post_type = 'product'
AND wp_posts.post_status = 'publish'
GROUP BY
wp_posts.ID
ORDER BY
wp_posts.menu_order,
wp_posts.post_title asc
LIMIT 0, 10