WordPress Query Help - mysql

Trying to build a somewhat complicated WordPress query. In one query, I'm trying to:
Pull all WordPress authors
Only authors with 10 or more published posts(what I'm having trouble with)
Sort authors by latest post.
Here is my original query:
SELECT wp_users.ID, display_name, user_url, user_email, MAX(post_date) as date FROM wp_users, wp_posts WHERE wp_users.ID = wp_posts.post_author AND wp_posts.post_status = 'publish' AND wp_posts.post_type = 'post' GROUP BY display_name ORDER BY date DESC;
This query returns all authors even those with 9 or less published posts.
Here is the query with the count for the posts:
SELECT wp_users.ID, display_name, user_url, user_email, MAX(post_date) as date, COUNT(post_date) as post_count FROM wp_users, wp_posts WHERE wp_users.ID = wp_posts.post_author AND wp_posts.post_status = 'publish' AND wp_posts.post_type = 'post' GROUP BY display_name ORDER BY date DESC;
In this query you can see that I've added:
COUNT(post_date) as post_count
Which returns everything beautifully.
It's only when I add this WHERE clause, does the query break
post_count > 9
I get this error message:
Unknown column 'post_count' in 'where clause'
Any idea why this is happing? My theories:
Won't work with grouping
or MySQL doesn't allow more than one AS statement
If you could shed some light, I would greatly appreciate it.
Thanks.

change the condition in the WHERE part of the query post_count > 9
with HAVING post_count > 9 after the GROUP BY
the final query will be SELECT wp_users.ID, display_name, user_url, user_email, MAX(post_date) as date, COUNT(post_date) as post_count FROM wp_users, wp_posts WHERE wp_users.ID = wp_posts.post_author AND wp_posts.post_status = 'publish' AND wp_posts.post_type = 'post' GROUP BY display_name HAVING post_count > 9 ORDER BY date DESC;

You're looking for the "HAVING" operator.
SELECT wp_users.ID, display_name, user_url, user_email, MAX(post_date) as date, COUNT(post_date) as post_count FROM wp_users, wp_posts WHERE wp_users.ID = wp_posts.post_author AND wp_posts.post_status = 'publish' AND wp_posts.post_type = 'post' GROUP BY display_name HAVING post_count>9 ORDER BY date DESC;

Related

How can I reduce MYSQL usage when sorting this index for a Wordpress site?

I received a note from Hostgator indicating that they've restricted my access to MYSQL because my site is using too many resources.
Normally, in a case like this, I'd just restore a backup to see if I recent change was producing the error. But, I haven't made any recent changes--apart from writing a few new posts.
Here's the report Hostgator included with their note--with my personal details removed:
Running Queries:
*************************** 1. row ***************************
USER: xxx_wrdp1
DB: xxx_wrdp1
STATE: Creating sort index
TIME: 1
COMMAND: Query
INFO: SELECT l.ID, post_title, post_content, post_name, post_parent,
post_author, post_status, post_modified_gmt, post_date, post_date_gmt
FROM ( SELECT wp_posts.ID
FROM wp_posts
WHERE wp\_posts.post\_status IN ('publish') AND
wp_posts.post_type = 'post'
AND wp_posts.post_password = ''
AND wp_posts.post_date != '0000-00-00 00:00:00'
ORDER BY wp_posts.post_modified ASC LIMIT 100 OFFSET 142200
)
o JOIN wp\_posts l ON [l.ID](https://l.ID) = [o.ID](https://o.ID)
If any can offer a suggestion on what's causing this the uptick in resource usage (or how it can be remedied), I'd be curious.
Thanks!
Why that query has an inner select from the same table? Is there a specific purpose? (I extracted the query from report you posted)
SELECT
l.ID,
post_title,
post_content,
post_name,
post_parent,
post_author,
post_status,
post_modified_gmt,
post_date,
post_date_gmt
FROM (
SELECT
wp_posts.ID
FROM wp_posts
WHERE wp_posts.post_status IN ('publish')
AND wp_posts.post_type = 'post'
AND wp_posts.post_password = ''
AND wp_posts.post_date != '0000-00-00 00:00:00'
ORDER BY wp_posts.post_modified ASC
) o
JOIN wp_posts l
ON l.ID = o.ID
If that was the case, i'd change the query to:
SELECT
ID,
post_title,
post_content,
post_name,
post_parent,
post_author,
post_status,
post_modified_gmt,
post_date,
post_date_gmt
FROM wp_posts
WHERE wp_posts.post_status IN ('publish')
AND wp_posts.post_type = 'post'
AND wp_posts.post_password = ''
AND wp_posts.post_date != '0000-00-00 00:00:00'
ORDER BY wp_posts.post_modified ASC
In this late example, you need to run the query with the EXPLAIN tag to check in which table/column it would require a proper index (usually when it says that rows count are bigger than 1).

how to get better performance, with not in query

here is my custom sql query ;
SELECT id,
post_title,
post_content,
comment_count,
post_date,
post_status,
post_name
FROM wp_posts
WHERE post_type = 'post'
AND post_status = 'publish'
AND id NOT IN (SELECT DISTINCT post_id
FROM wp_postmeta
WHERE meta_key = 'visible_headlane'
AND meta_value = 'On')
AND id NOT IN (SELECT DISTINCT post_id
FROM wp_postmeta
WHERE meta_key = 'visible_homepage'
AND meta_value = 'On')
ORDER BY post_date DESC
LIMIT 11, 32
i can not use, LIMIT in NOT IN Query so, there is any way to use, or limit SELECT DISTINCT sql query, or any idea ?
Note : I need to optimise this query because, it takes so long , like a slow query.
Thanks.
Switch to NOT EXISTS( SELECT 1 FROM ... ) -- this variation does not need to compute the entire list of things; it only needs to check for the absence. LEFT JOIN .. ON .. IS NULL is also more efficient.
Furthermore, the standard schema for wp_postmeta is quite inefficient; see my suggestions.
Meanwhile, keep it as two tests, unlike the suggestion by 'holder'.
The EXISTS would look something like
AND NOT EXISTS ( SELECT 1 FROM wp_postmeta
WHERE post_id = wp_posts.id
AND meta_key = 'visible_headlane'
AND meta_value = 'On' )
which would make good use of the PRIMARY KEY(post_id, meta_key) that I recommend.
(Is it really 'headlane', not 'headline'?)
Maybe something like this as jarlh suggested
SELECT
ID,post_title,post_content,comment_count,post_date,post_status,post_name
FROM wp_posts t1
left join (
SELECT DISTINCT post_id from wp_postmeta
WHERE meta_key IN ('visible_headlane','visible_homepage') AND meta_value = 'On' ) t2 on t1.ID = t2.post_id
WHERE post_type = 'post'
AND post_status = 'publish'
AND t2.post_id is null
ORDER BY post_date DESC
LIMIT 11, 32

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

Return up to 5 of each 'post_type' in a DB table

I have a query that returns all posts from a DB table that match the given criteia, but I'm looking for a way to only return up to 5 posts from each 'post_type'. Currently the query is selecting every single post that matches and I am having to limit the numbers from each 'post_type' in PHP, which is not particularly efficient.
Can this be done? Thanks.
SELECT ID, post_title, post_type
FROM wp_posts
WHERE 1=1
AND post_status = "publish"
AND (
post_type IN (
"staff"
)
AND post_name LIKE "%The%"
)
OR (
post_type NOT IN (
"staff",
"Attachment"
)
AND (
post_name LIKE "%The%"
OR post_title LIKE "%The%"
)
)
ORDER BY post_type, post_name ASC
This solution will select the five most recent (based on id) posts per post_type:
SELECT a.id, a.post_title, a.post_type
FROM wp_posts a
INNER JOIN wp_posts b ON a.post_type = b.post_type AND a.id <= b.id
WHERE a.post_status = 'publish' AND
(a.post_type = 'staff' AND a.post_name LIKE '%The%') OR
(a.post_type NOT IN ('staff', 'Attachment') AND (a.post_name LIKE '%The%' OR a.post_title LIKE '%The%'))
GROUP BY a.id, a.post_title, a.post_type
ORDER BY a.post_type, a.post_name
HAVING COUNT(1) <= 5

Weird issue with orber by, inner join in wordpress query

I am working on a custom plugin in wordpress. I have a weird issue with one sql.
SQL:
SELECT SQL_CALC_FOUND_ROWS wp_posts. *
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 )
WHERE 1 =1
AND wp_term_taxonomy.taxonomy = 'category'
AND wp_term_taxonomy.term_id IN ('23')
AND (
wp_posts.post_author =1
)
AND wp_posts.post_type = 'post'
AND (
wp_posts.post_status = 'publish'
OR wp_posts.post_status = 'private'
)
GROUP BY wp_posts.ID
ORDER BY `wp_posts`.`as_stats_rating` DESC
LIMIT 0 , 30
Its returning the correct data but its not sorting results according to as_stats_rating.
I am stumped. Does anyone know what I am doing wrong?
Edit 1 : Update
Here is the structure of wp_posts:
Sample result:
ID as_stats_rating
1221 8
1222 10
All fields in sample results are :
ID post_author post_date post_date_gmt post_content post_title post_excerpt post_status comment_status ping_status post_password post_name to_ping pinged post_modified post_modified_gmt post_content_filtered post_parent guid menu_order post_type post_mime_type comment_count as_stats_numviews as_stats_numvotes as_stats_votestotal as_stats_rating
By the way, its not only about 'order by wp_posts.as_stats_rating', 'order by wp_posts.as_stats_numviews' have the same issue. (just to clear up, if you are wondering about as_stats_rating having varchar type)
Any chance that the as_stats_rating field is a string (char/text) datatype and not a numeric (float/int/decimal) datatype?