Mysql self inner join query? - mysql

When i run the below query in mysql it took 78 sec to display record. Is there other way to write this query. Here is my
mysql query -> "
select distinct nuqta1.post_id from wp_postmeta as nuqta1
inner join wp_postmeta as nuqta2 on (nuqta1.post_id = nuqta2.post_id)
inner join wp_postmeta as nuqta4 on (nuqta1.post_id = nuqta4.post_id)
inner join wp_postmeta as nuqta5 on (nuqta1.post_id = nuqta5.post_id)
inner join wp_postmeta as nuqta6 on (nuqta1.post_id = nuqta6.post_id)
inner join wp_postmeta as nuqta7 on (nuqta1.post_id = nuqta7.post_id)
inner join wp_postmeta as nuqta8 on (nuqta1.post_id = nuqta8.post_id)
inner join wp_postmeta as nuqta9 on (nuqta1.post_id = nuqta9.post_id)
inner join wp_postmeta as nuqta10 on (nuqta1.post_id = nuqta10.post_id)
inner join wp_postmeta as nuqta11 on (nuqta1.post_id = nuqta11.post_id)
inner join wp_postmeta as nuqta12 on (nuqta1.post_id = nuqta12.post_id)
where (nuqta2.meta_key = 'checkin' and nuqta2.meta_value LIKE '%10/31/2012%')
and (nuqta4.meta_key = 'guests' and nuqta4.meta_value ='1')
and (nuqta5.meta_key = 'roomtype' and nuqta5.meta_value LIKE '%Entire home/apt%')
and (nuqta6.meta_key = 'price' and cast(nuqta6.meta_value as signed) BETWEEN '10' and '99999')
and (nuqta7.meta_key = 'amenities' and nuqta7.meta_value LIKE '%Wireless Internet%')
and (nuqta8.meta_key = 'amenities' and nuqta8.meta_value LIKE '%TV%')
and (nuqta9.meta_key = 'amenities' and nuqta9.meta_value LIKE '%Kitchen%')
and (nuqta10.meta_key = 'amenities' and nuqta10.meta_value LIKE '%Wireless Internet%')
and (nuqta11.meta_key = 'amenities' and nuqta11.meta_value LIKE '%TV%')
and (nuqta12.meta_key = 'amenities' and nuqta12.meta_value LIKE '%Kitchen%')
and 1=1 order by nuqta1.post_id asc
".
And and i am using wordpress table wp_postmeta to run this query

You have a lot of LIKE '%whatever%' clauses in this query. Each of these clauses necessarily causes a full table scan of wp_postmeta. It's actually pretty good that you got them done in less than ten seconds each.
If you know more about your meta_value column's values, so you can use LIKE 'whatever%' (getting rid of the leading % wildcard term) you'll speed things up a lot.
Also it's not clear why you have nuqta10, nuqta11, nuqta12. Those seem to search for the same stuff as 7,8,9. Considering the cost of the searches, you might consider eliminating those.

Try using Fulltext Search
What you'll do is something like
SELECT
*
FROM
tableName
WHERE
MATCH ( columnName ) AGAINST ( 'Keyword1', 'Keyword2', 'Keyword3' )

Related

Modifying MySQL Query for WpDataTables

I am building a table in WpDataTables that involves two custom post types: 'applicants' and 'reviews'. I am trying to create a table that shows all of the applicants that have either been reviewed by the current user (reviewer) who is viewing the WpDataTable. Each applicant can have one or more reviews.
This query runs exactly like I want it to in MySQL, however, WpDataTables does not like it for some reason. I believe it is because of the subquery.
SELECT a.ID, r.post_title, a.post_title, a.guid, r.post_type, a.post_type, r.post_author,
b.meta_value review_app_score,
c.meta_value review_app_comment
FROM (SELECT * FROM `wppm_2_posts` WHERE post_author = 1 AND post_type = 'reviews' AND post_status = 'publish') as r
RIGHT JOIN `wppm_2_posts`as a ON r.post_title = a.ID
LEFT JOIN `wppm_2_postmeta` b ON r.ID = b.post_id AND b.meta_key='review_app_score'
LEFT JOIN `wppm_2_postmeta` c ON r.ID = c.post_id AND c.meta_key='review_app_comment'
WHERE a.post_type = 'applicants'
AND a.post_status = 'publish'
Here is what the MySQL results:
https://i.stack.imgur.com/KzvHt.png
This is exactly what I am needing, except I need it to work in WpDataTables.
The reason is that I am looking to take advantage of their dynamic placeholder (%CURRENT_USER_ID%) instead of the '1' in the subquery above for post_author.
Such as:
(SELECT * FROM `wppm_2_posts` WHERE post_author = %CURRENT_USER_ID% AND post_type = 'reviews' AND post_status = 'publish')
Is there another way I could write this without using a subquery? Or there is another way to build this without needing the dynamic placeholder such as PHP?
Any help is appreciated.
Here is the professional way (AKA it wasn't me) of writing the query. Not sure if it will help anyone else but hopefully it will.
SELECT
APPLICANTS.ID AS applicants_id
,APPLICANTS.post_title AS applicants_post_title
,APPLICANTS.guid AS applicants_guid
,APPLICANTS.post_type AS applicants_post_type
,REVIEWS.post_author AS reviews_author_id
,REVIEWS.post_type AS reviews_post_type
,REVIEWS.post_title AS reviews_post_title
,R_APP_SCORES.meta_value AS review_app_score
,R_APP_COMMENTS.meta_value AS review_app_comment
FROM
`%WPDB%posts` AS APPLICANTS
LEFT JOIN
`%WPDB%posts` AS REVIEWS ON
(REVIEWS.post_author = %CURRENT_USER_ID%) AND
(REVIEWS.post_title = APPLICANTS.ID) AND
(REVIEWS.post_type = 'reviews') AND
(REVIEWS.post_status = 'publish')
LEFT JOIN
`%WPDB%postmeta` R_APP_SCORES ON
(R_APP_SCORES.post_id = REVIEWS.ID) AND
(R_APP_SCORES.meta_key = 'review_app_score')
LEFT JOIN
`%WPDB%postmeta` R_APP_COMMENTS ON
(R_APP_COMMENTS.post_id = REVIEWS.ID) AND
(R_APP_COMMENTS.meta_key = 'review_app_comment')
WHERE
(APPLICANTS.post_type = 'applicants') AND
(APPLICANTS.post_status = 'publish')

Multiple Meta_Key Select on on Wordpress database

I've developed a query which selects events from Wordpress. I am using the where clause to select where the meta_value of the meta_key eventstartdate is after today.
The issue I'm having now is, I also want filter on a second meta_value that being from the meta_key '_VenueCity'.
I have tried aliasing the wp_postmeta table and doing a where on the meta_key but I think I'm missing a join.
This is the code that works without my additional code to get it to work. Can any one advise on how I get this to work?
SELECT
`wp_posts`.`ID` AS `EventID`,
`wp_posts`.`post_parent` AS `SeriesID`,
`wp_posts`.`post_title` AS `EventTitle`,
`wp_posts`.`post_content` AS `EventDescription`,
`wp_posts`.`post_excerpt` AS `EventSummary`,
`wp_posts`.`post_name` AS `EventSlug`,
min(`wp_postmeta`.`meta_value`) AS `EventStartDate`,
max(`tribe_event_end_date`.`meta_value`) AS `EventEndDate`,
`wp_posts`.`guid` AS `GUID`
FROM ((`wp_posts`
JOIN `wp_postmeta` ON
(
(`wp_posts`.`ID` = `wp_postmeta`.`post_id`)
))
LEFT JOIN `wp_postmeta` `tribe_event_end_date` ON
(
(
(`wp_posts`.`ID` = `tribe_event_end_date`.`post_id`) AND
(`tribe_event_end_date`.`meta_key` = '_EventEndDate')
)
))
WHERE
(
(`wp_postmeta`.`meta_key` = '_EventStartDate') AND
(`wp_posts`.`post_type` = 'tribe_events') AND
(`wp_posts`.`post_status` = 'publish') AND
(`tribe_event_end_date`.`meta_value` >= CURDATE())
)
GROUP BY
`wp_posts`.`ID`
ORDER BY
`EventStartDate`,
`wp_posts`.`post_date`;
I am not going to write your query for you but I will give an example of how to get multiple postmeta values. The power will be in the where clause to get the right values.
You should also consider what joins you want to use.
SELECT
p.post_title,
pm1.meta_value,
pm2.meta_value
FROM wp_posts as p
INNER JOIN wp_postmeta as pm1
ON p.ID = pm1.post_id
INNER JOIN wp_postmeta as pm2
ON p.ID = pm2.post_id
WHERE
pm1.meta_key = '_my_postmeta_field1'
AND
pm2.meta_key <> '_not_this_field'

How to fix an SQL query which has a specifying table twice error

I have this query:
SELECT *
FROM `wp_postmeta`
WHERE `meta_key` = '_test'
AND `post_id` IN (SELECT post_id FROM `wp_postmeta`
where meta_value = 8023)
Returns the SQL error:
Table 'wp_postmeta' is specified twice, both as a target for 'UPDATE'
and as a separate source for data
I have read other answers and attempting to add a further SELECT * FROM ( ) around the sub query but didn't help.
I assume I need some form of AS in here but can't figure out the exact code.
Can you rewrite the query in the format that won't trigger the error?
The same for this similar query:
UPDATE wp_postmeta
SET meta_value = 5.55
WHERE meta_key = '_regular_price'
AND post_id IN (
SELECT post_id
FROM wp_postmeta
WHERE meta_value = 8023
)`
You can use alias for table name
(and as suggestion in your case you can also use join instead of in )
SELECT a.*
FROM `wp_postmeta` a
inner join `wp_postmeta` b on a.`post_id = b.post_id
where a.`meta_key` = '_test'
and b.meta_value = 8023
In update you could use a join with subselect for circumvent the limits due to update actions on the same table
UPDATE wp_postmeta a
inner join (
SELECT post_id
FROM wp_postmeta
WHERE meta_value = 8023
) t on a.`post_id = t.post_id and a.`meta_key` = '_test'
SET meta_value = 5.55
SELECT * FROM wp_postmeta as wp_out
WHERE wp_out.meta_key = '_test'
AND wp_out.post_id IN
( SELECT wp_in.post_id
FROM wp_postmeta as wp_in
where wp_in.meta_value = 8023)
Although this is not a good answer, but it is effective, ha ha..
SELECT *
FROM wp_postmeta
WHERE meta_key = '_test'
AND post_id IN (SELECT GROUP_CONCAT(post_id) FROM wp_postmeta
where meta_value = 8023)
The SELECT query posted in the question is equivalent to this one:
SELECT p1.*
FROM `wp_postmeta` p1
INNER JOIN `wp_postmeta` p2 ON p1.`post_id` = p2.`post_id`
WHERE p1.`meta_key` = '_test'
AND p2.`meta_value` = 8023
In fact, if some conditions are met, the MySQL engine converts the original SELECT query into a query similar to this as an optimization.
This SELECT query can be easily changed into the desired UPDATE query:
UPDATE `wp_postmeta` p1
INNER JOIN `wp_postmeta` p2 ON p1.`post_id` = p2.`post_id`
SET p1.`meta_values` = 5.55
WHERE p1.`meta_key` = '_test'
AND p2.`meta_value` = 8023

How to get Wordpress post with title, content and featured image using mysql query

Hi I know this question may seems familiar but please read the full question.
I want to get Wordpress post title,featured image,content using a mysql query.
I tried many queries but I'm getting errors.
there is no error and MySQL query returns empty. I am using Wordpress version 4.5.2.
I found this query but it is giving me an empty result.
SELECT p1.*, wm2.meta_value
FROM wp_posts p1
LEFT JOIN wp_postmeta wm1 ON (
wm1.post_id = p1.id
AND wm1.meta_value IS NOT NULL
AND wm1.meta_key = '_thumbnail_id'
)
LEFT JOIN
wp_postmeta wm2
ON (
wm1.meta_value = wm2.post_id
AND wm2.meta_key = '_wp_attached_file'
AND wm2.meta_value IS NOT NULL
)LEFT JOIN
wp_term_relationships wtr
ON
(
object_id=p1.id
)
WHERE
p1.post_status='publish'
AND p1.post_type='post'
AND 'term_taxonomy_id'='454'
ORDER BY p1.post_date DESC
LIMIT 0,10
How can I improve this query to return results?
You have an error in SQL's WHERE clause:
AND 'term_taxonomy_id'='454'
The string 'term_taxonomy_id' will never be equal to the string '454'.
First, to check, remove this condition entirely from your query. If you get results back and you still want to filter by this taxonomy_id then remove the single quote marks around the field name:
SELECT p1.*,
wm2.meta_value
FROM wp_posts p1
LEFT JOIN wp_postmeta wm1 ON (
wm1.post_id = p1.id
AND wm1.meta_value IS NOT NULL
AND wm1.meta_key = '_thumbnail_id'
)
LEFT JOIN wp_postmeta wm2 ON (
wm1.meta_value = wm2.post_id
AND wm2.meta_key = '_wp_attached_file'
AND wm2.meta_value IS NOT NULL
)
LEFT JOIN wp_term_relationships wtr ON (object_id = p1.id)
WHERE p1.post_status = 'publish'
AND p1.post_type = 'post'
AND term_taxonomy_id = '454'
ORDER BY p1.post_date DESC LIMIT 0,10
In MySQL you can use backticks around field names, but single quotes are used around string literals. If you mix those up, you'll be in trouble.
If you are still not getting results consider removing the p1.post_status and p1.post_type restrictions to see if you get results back and tweak accordingly.

How do I perform a between Query on a DB that all ready has multiple joins?

I am trying to write a query to check if the custom meta values in a custom post type(properties) when saved equals the meta values in another custom post type(alerts)
I can get this work for normal match fields however I am trying to get it to work for a range for example, if 'bedrooms' in 'properties' is between 'a_bedrooms_min' and 'a_bedrooms_max' in 'alerts'. My Query looks like this so far:
//Property Meta Fields
$meta_type = 'flat';
$meta_bedrooms = '2';
//Alert Meta Fields
a_bedrooms_min = 1
a_bedrooms_max = 3
SELECT ID
FROM wp_posts
INNER JOIN wp_postmeta m1
ON ( wp_posts.ID = m1.post_id )
INNER JOIN wp_postmeta m2
ON ( wp_posts.ID = m2.post_id )
INNER JOIN wp_postmeta m3
ON ( wp_posts.ID = m3.post_id )
WHERE
wp_posts.post_type = 'alerts'
AND wp_posts.post_status = 'publish'
AND ( m1.meta_key = 'a_property_type' AND m1.meta_value = '$meta_type' )
AND ( m2.meta_key = 'a_bedrooms_min' AND m2.meta_value >= '$meta_bedrooms' )
AND ( m3.meta_key = 'a_bedrooms_max' AND m3.meta_value <= '$meta_bedrooms' )
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date
DESC;
The last two ANDs obviously will not work with what I am trying to do but how would can get this to work?
Thanks
Robert
I think you are close. you have a hybrid old ANSI vs more explicit JOIN. As you can see in this example, each one of the 3 criteria is joined to the meta table on all 3 parts explicitly. So, the ID should only appear ONCE per ID as each of the meta SHOULD AT MOST return one record, and the record will only qualify if all 3 meta find the respective match.
SELECT
ID
FROM
wp_posts
INNER JOIN wp_postmeta m1
ON wp_posts.ID = m1.post_id
AND m1.meta_key = 'a_property_type'
AND m1.meta_value = '$meta_type'
INNER JOIN wp_postmeta m2
on wp_posts.ID = m2.post_id
AND m2.meta_key = 'a_bedrooms_min'
AND m2.meta_value <= '$meta_bedrooms'
INNER JOIN wp_postmeta m3
on wp_posts.ID = m3.post_id
AND m3.meta_key = 'a_bedrooms_max'
AND m3.meta_value >= '$meta_bedrooms'
WHERE
wp_posts.post_type = 'alerts'
AND wp_posts.post_status = 'publish'
GROUP BY
wp_posts.ID
ORDER BY
wp_posts.post_date DESC;
I've revised as I believe the <= and >= were actually backwards. For example, your MINIMUM bedrooms from the meta_value was 1 and max is 3... you are LOOKING for 2 to be qualified.
So, you NEED MIN_BEDROOMS <= 2 and the 2 <= MAX_BEDROOMS
what was originally presented is MIN_BEDROOMS >= 2 (1 is never greater than 2)
and MAX_BEDROOMS <= 2 (2 is never less than 2).
Try again.