Using MySQL LIMIT on query with LEFT JOIN - mysql

I'm doing the following query in MySQL:
SELECT wp_posts.post_date, wp_posts.post_content, wp_posts.post_title, wp_posts.ID, wp_terms.name, wp_term_taxonomy.taxonomy
FROM wp_posts
LEFT JOIN wp_term_relationships ON ( wp_term_relationships.object_id = wp_posts.ID )
LEFT JOIN wp_term_taxonomy ON ( wp_term_taxonomy.term_taxonomy_id = wp_term_relationships.term_taxonomy_id )
LEFT JOIN wp_terms ON ( wp_terms.term_id = wp_term_taxonomy.term_id )
WHERE 1=1
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish')
ORDER BY wp_posts.ID DESC
LIMIT 50
This returns 50 results as expected : But dependant on the number of 'terms' per 'post', this would mean an indeterminate number of 'posts'.
How can I limit it so that I get 25 unique wp_posts
WHERE 1=1
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish')
But return as many rows as I need with regards to joined wp_terms... ?
Thanks!

If due to LEFT joins, there may be more than one entry for a given ID, I would pre-query from your posts, the most recent 25 IDs that qualify as your left-joins are optional and you are always getting the ID. Limit this to 25. Now, when applying the ORDER BY to the JustLast25.ID, will put as many sequentially assigned entries along with it. So, your 25 IDs could generate 200 entries, but for each ID, they will be assigned a sequence of 1, 2, 3, etc...
After that is all wrapped-up, in order to get your 50 record limit, but ensuring you have all 25 of your IDs, you need to re-query from that, but change the order to the sequence FIRST, then the ID so you get the 1st entry for every possible, then 2nd for every possible, then 3rd, etc... Some may have no entries, but a minimum, they will be included in the list once. For those that have more than one, their additional records will appear after the first run
select
PreQualify.*
from
( SELECT
JustLast25.post_date,
JustLast25.post_content,
JustLast25.post_title,
JustLast25.ID,
wp_terms.name,
wp_term_taxonomy.taxonomy,
#lastSeq := if( #lastID = JustLast25.id, #lastSeq +1, 1 ) as SeqPerID,
#lastID := JustLast25.ID
FROM
( select #lastID := 0, #lastSeq := 0 ) sqlvars,
( select wp_posts.*
from wp_posts
where wp_posts.post_type = 'post'
AND wp_posts.post_status = 'publish'
ORDER BY
wp_posts.ID DESC
LIMIT 25 ) JustLast25
LEFT JOIN wp_term_relationships
ON JustLast25.ID = wp_term_relationships.object_id
LEFT JOIN wp_term_taxonomy
ON wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id
LEFT JOIN wp_terms
ON wp_term_taxonomy.term_id = wp_terms.term_id
order by
JustLast25.ID DESC ) PreQualify
order by
PreQualify.SeqPerID,
PreQualify.ID DESC
LIMIT 50
Now, if you want them all to be grouped with all the records next to their sequentially qualified postings, you'll have to wrap that up one more level into
select
FinalSet.*
from
( full query from above ) FinalSet
order by
FinalSet.ID DESC,
FinalSet.SeqPerID

Related

How to delete entries from a SELECT query result in mysql?

I have the following SQL query :
SELECT wp_posts.* , wicl_translations.*
FROM wp_posts wp_posts join wp_icl_translations wicl_translations
ON (wicl_translations.element_id = wp_posts.ID)
WHERE (wicl_translations.language_code = 'es-es'
AND wicl_translations.element_type ='post_product'
AND wp_posts.post_type = 'product' ) GROUP BY wp_posts.ID
This returns all the results I need to delete from my database so I have tried several DELETE queries but getting syntax errors in all of them .
Example :
DELETE FROM wp_posts
WHERE (
SELECT wp_posts.* , wicl_translations.*
FROM wp_posts wp_posts join wp_icl_translations wicl_translations
ON (wicl_translations.element_id = wp_posts.ID)
WHERE (wicl_translations.language_code = 'pt-pt'
AND wicl_translations.element_type ='post_product'
AND wp_posts.post_type = 'product' ) GROUP BY wp_posts.ID
)
);
Also tried this :
DELETE FROM wp_posts WHERE wp_posts.ID = ANY IN (
SELECT wp_posts.ID, wicl_translations.*
FROM wp_posts wp_posts join wp_icl_translations wicl_translations
ON (wicl_translations.element_id = wp_posts.ID)
WHERE (wicl_translations.language_code = 'es-es'
AND wicl_translations.element_type ='post_product'
AND wp_posts.post_type = 'product' ) GROUP BY wp_posts.ID
)
It`s a complex aggregated query and I lack the mysql knowledge to properly write a rule for deleting these results .
How could I approach this ?
Thanks
If we have a complex query that returns the id value of rows in wp_posts that we want to delete (assuming that id is the primary key or a unique key of a row in the table)... as an example
SELECT p.id
FROM wp_posts p
JOIN wp_icl_translations t
ON t.element_id = p.id
WHERE t.language_code = 'es-es'
AND t.element_type = 'post_product'
AND p.post_type = 'product'
GROUP
BY p.id
We can then use that query as an inline view. We wrap the query in parens and reference it in the FROM clause of another query. MySQL requires that we assign an alias to thhe inline view (or derived table in the MySQL vernacular).
We can join the result from the inline view that back to the table we want to remove rows from. We write this a SELECT statement first
SELECT r.*
FROM ( -- inline view
SELECT p.id
FROM wp_posts p
JOIN wp_icl_translations t
ON t.element_id = p.id
WHERE t.language_code = 'es-es'
AND t.element_type = 'post_product'
AND p.post_type = 'product'
GROUP
BY p.id
) q
JOIN wp_posts r
ON r.id = q.id
to return the set of rows to be removed. We can verify that this is the intended set, or insert (create table as) the set of rows into backup...
Once we are confident that the SELECT is returning the rows we want to remove, we can convert it into a DELETE statement by replacing the SELECT keyword with DELETE.
DELETE r.*
FROM ( -- inline view
SELECT p.id
FROM wp_posts p
JOIN wp_icl_translations t
ON t.element_id = p.id
WHERE t.language_code = 'es-es'
AND t.element_type = 'post_product'
AND p.post_type = 'product'
GROUP
BY p.id
) q
JOIN wp_posts r
ON r.id = q.id
You'r on the right track !
You just miss the correct WHERE condition :
DELETE FROM wp_posts WHERE wp_posts.ids IN (...)
Make sure the result has only one column wich you shall refer to when deleting data from the targetted tables. The delete queries will be equal to the number of tables you will require to delete from ie.
DELETE FROM table_1 where common_column in (YOUR_SELECT_QUERY);
DELETE FROM table_2 where common_column in (YOUR_SELECT_QUERY);
DELETE FROM table_3 where common_column in (YOUR_SELECT_QUERY);
DELETE FROM table_nth where common_column in (YOUR_SELECT_QUERY);
Your select query be like,
SELECT GROUP_CONCAT(temp_tbl.ID) FROM (SELECT wp_posts.* , wicl_translations.*
FROM wp_posts wp_posts join wp_icl_translations wicl_translations
ON (wicl_translations.element_id = wp_posts.ID)
WHERE (wicl_translations.language_code = 'es-es'
AND wicl_translations.element_type ='post_product'
AND wp_posts.post_type = 'product' ) GROUP BY wp_posts.ID) AS temp_tbl

Category page main query load too much when it has hundreds of sub category in wordpress

I have main category "Albums" and all the Album_Names as sub category.
When I try to open category-albums.php page or say Album category page its take too much load.
Below query fired.
SELECT wp_posts.ID
FROM wp_posts
LEFT JOIN wp_term_relationships
ON (wp_posts.ID = wp_term_relationships.object_id)
WHERE 1=1
AND ( wp_term_relationships.term_taxonomy_id IN (4,5,6,
7,8,9,10,11,12,13,14,15,16,17,18,....,5000) )
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish')
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC
LIMIT 0, 30
How to optimize this query? I don't want to show any post in page.
I want to show only child category list by name instead of post.
Some optimization tips
SELECT wp_posts.ID
FROM wp_posts
-- LEFT -- probably misleading
JOIN wp_term_relationships
ON (wp_posts.ID = wp_term_relationships.object_id)
WHERE
-- 1=1 AND -- junk
( wp_term_relationships.term_taxonomy_id IN (4,5,6,
7,8,9,10,11,12,13,14,15,16,17,18,....,5000) )
-- Could that changed to be "BETWEEN 4 and 5000" ?
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish')
GROUP BY wp_posts.ID
ORDER BY wp_posts.ID DESC -- same(?) effect, much better optimization
LIMIT 0, 30
Indexes:
wp_posts: (post_type, post_status, ID)
wp_term_relationships: (object_id, term_taxonomy_id)

mysql sum returning wrong value

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

How to get result count from mysql inner join

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?

MySQL query with SUM and order

What is wrong with my query? Can somebody help me please?
I get this errormessage
"Unknown column 'wp_gdsr_data_article.
(SUM(user_voters)+SUM(visitor_voters))' in 'order clause'"
but the 'wp_gdsr_data_article' colum exist
SELECT *
FROM `wp_posts`
INNER JOIN wp_term_relationships ON wp_term_relationships.object_id = ID AND wp_term_relationships.term_taxonomy_id = 1
INNER JOIN wp_gdsr_data_article ON post_id = ID
WHERE `post_status` = 'publish'
AND `post_type` = 'post'
ORDER BY `wp_gdsr_data_article`.`(SUM(user_voters)+SUM(visitor_voters))` DESC
LIMIT 1 , 30
You are using an expression in the ORDER clause which not a table's column.
Hence you can't use a table identifier on the outcome of an expression.
This is wrong.
ORDER BY `wp_gdsr_data_article`.`(SUM(user_voters)+SUM(visitor_voters))` DESC
Change it to:
ORDER BY (SUM(user_voters)+SUM(visitor_voters)) DESC
And you can't directly use any aggregate function in ORDER BY clause like that.
Calculate SUM... parts separately and then use in ORDER BY.
SELECT * from (
SELECT *, (SUM(user_voters)+SUM(visitor_voters)) total
FROM `wp_posts`
INNER JOIN wp_term_relationships
ON wp_term_relationships.object_id = ID
AND wp_term_relationships.term_taxonomy_id = 1
INNER JOIN wp_gdsr_data_article
ON post_id = ID
WHERE `post_status` = 'publish'
AND `post_type` = 'post'
LIMIT 1 , 30
) results
ORDER BY total
Refer to: How to ORDER BY a SUM() in MySQL?
Remove quotes from all columns and tablenames in your statement. Besides the Order by part should base on a column or an evaluated value in our statement, the way you use it is wrong. you will need to evaluate the part which you use in the order by section before using it for the order by, something like this (untested):
SELECT (SUM(wp_gdsr_data_article.user_voters)+SUM(wp_gdsr_data_article.visitor_voters) as total_voters), *
FROM wp_posts
INNER JOIN wp_term_relationships
ON wp_term_relationships.object_id = ID
AND wp_term_relationships.term_taxonomy_id = 1
INNER JOIN wp_gdsr_data_article
ON post_id = ID
WHERE post_status = 'publish' AND post_type = 'post'
ORDER BY total_voters DESC
LIMIT 1 , 30
Try this
SELECT *, (SUM(wp_gdsr_data_article.user_voters)+SUM(wp_gdsr_data_article.visitor_voters)) AS someSum
FROM `wp_posts`
INNER JOIN wp_term_relationships ON wp_term_relationships.object_id = ID AND wp_term_relationships.term_taxonomy_id = 1
INNER JOIN wp_gdsr_data_article ON post_id = ID
WHERE `post_status` = 'publish'
AND `post_type` = 'post'
ORDER BY someSum DESC
LIMIT 1 , 30