MYSQL Query Joining Tables - mysql

Here is my query as is for a WP database.
$letters = $wpdb->get_col(
"SELECT DISTINCT LEFT(post_title,1) AS first_letter FROM $wpdb->posts
WHERE post_type = '$post_type' AND post_status = 'publish'
ORDER BY first_letter ASC"
);
It is a baby name database and I want to make a widget to separate male/female so I need to do a query like above but to get posts with only certain postmeta which below is the key and value I am looking for.
Key - spin2
Value - Male
How do I add this into the query since it is in a different table?
Thanks!

You just need to use an INNER JOIN:
SELECT DISTINCT LEFT(posts.post_title,1) AS first_letter
FROM $wpdb->posts AS posts
INNER JOIN $wpdb->postmeta AS meta
ON posts.ID = meta.post_id
WHERE posts.post_type = '$post_type'
AND posts.post_status = 'publish'
AND meta.meta_key = 'spin2'
AND meta.meta_value = 'Male'
ORDER BY first_letter ASC

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

Querying WordPress DB from normal sql

Disclaimer: I am not going to use any other ways I have a specific requirement.
All I want is to Join from posts table to the posts meta so that I can get the featured image per post. I am able to get the post via where clause post type is post and published but I don't know how to write join for MySql to get the featured image of each post
You may try something like this:
$sql = "
SELECT $wpdb->posts.*
FROM $wpdb->posts, $wpdb->postmeta
WHERE $wpdb->posts.ID = $wpdb->postmeta.post_id
AND $wpdb->posts.post_status = 'publish'
AND $wpdb->posts.post_type = 'post'
ORDER BY $wpdb->posts.post_date DESC
";
// Get an array of objects
$posts = $wpdb->get_results($sql, OBJECT);
You may check more here.
If someone else is still looking for the sql needed here you go
SET #term = "someterm"
SELECT DISTINCT
posts.id,
posts.post_author,
posts.post_title,
posts.post_date,
LEFT(posts.post_content,300) post_content,
wpmeta.meta_value thumbnail
FROM wp_posts posts
INNER JOIN wp_postmeta wpm ON posts.id = wpm.post_id
INNER JOIN wp_postmeta wpmeta ON wpm.meta_value = wpmeta.post_id
LEFT JOIN wp_term_relationships rel ON rel.object_id = posts.ID
LEFT JOIN wp_term_taxonomy tax ON tax.term_taxonomy_id = rel.term_taxonomy_id
LEFT JOIN wp_terms t ON t.term_id = tax.term_id
WHERE
post_status = 'publish'
AND posts.post_type = 'post'
AND wpm.meta_key = '_thumbnail_id'
AND wpmeta.meta_key = '_wp_attached_file'
AND 1 =
CASE
WHEN #term IS NULL THEN 1
WHEN #term IS NOT NULL AND t.term_id = #term THEN 1
ELSE 0
END
ORDER BY post_date DESC

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

combine two sql queries -

I've have two sql queries which I'm trying to combine
The first:
SELECT * FROM wp_posts
JOIN wp_postmeta on (post_id=ID)
WHERE meta_key = "packageID" and meta_value = 1
ORDER BY post_date limit 50
Joins the wordpress wp_post table to the wp_postmeta and gets all the posts meeting with packageID = 1 (I think it might be an inelegant way of doing it but it works)
The second
SELECT * FROM wp_postmeta
JOIN wp_posts ON (meta_value=ID)
WHERE post_id = 2110
AND meta_key = '_thumbnail_id'
again joins the wp_post table to the wp_postmeta table, so for the post with the id 2110 it successfully gets the thumbnail for that posts. NB 2110 is just an example of an id
In Wordpress a thumbnail is a kind of post. So in this example the text which constitutes post 2110 is a associated with post 2115 - the latter being the thumbnail
What I'm trying to do is get the list as in the first query but also get thumbnails associated with each post
I think I need two joins but I can't see how to do it (being an sql beginner)
NB this will be in a script outside Wordpress so I can't use Wordpress's built-in functions
You can try this one,if there are more than one thumbnails for the post you can get the list of thumbnails separated by comma
SELECT
*,
(SELECT
GROUP_CONCAT(meta_value)
FROM
wp_postmeta
WHERE post_id = wp.ID
AND wpm.meta_key = "_thumbnail_id") AS `thumbnails`
FROM
wp_posts wp
JOIN wp_postmeta wpm
ON (wpm.post_id = wp.ID)
WHERE wpm.meta_key = "packageID"
AND wpm.meta_value = 1
ORDER BY wp.post_date
LIMIT 50
Note : GROUP_CONCAT has a limit to concat characters but you
can increase this limit
To get only one thumbnail you can try this
SELECT
*,
(SELECT
(meta_value)
FROM
wp_postmeta
WHERE post_id = wp.ID
AND wpm.meta_key = "_thumbnail_id" LIMIT 1)
FROM
wp_posts wp
JOIN wp_postmeta wpm
ON (wpm.post_id = wp.ID)
WHERE wpm.meta_key = "packageID"
AND wpm.meta_value = 1
ORDER BY wp.post_date
LIMIT 50
try with the following code
SELECT * FROM wp_posts wp JOIN wp_postmeta wm on (wp.post_id=wm.ID) WHERE wp.meta_key = "packageID" and wp.meta_value = 1 ORDER BY wp.post_date limit 50;
use proper alias and try it.
Try using the post_type column. The attachments have a post_type of 'attachment'. I can further explain if needed.
Also the post to which the thumbnail is attached to will be in the column post_parent.
global $wpdb;
$query7 = "SELECT distinct wp_postmeta.meta_value, wp_postmeta.meta_key, 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 wp_posts.ID = wp_postmeta.post_id
AND wp_posts.post_status = 'publish'
AND wp_postmeta.meta_key = 'packageID'
AND wp_postmeta.meta_value = 1
AND (mt1.meta_key LIKE '_thumbnail_id')
$output = $wpdb->get_results( $query7 );
Use join with different aliases when joining same table more than once.
Hope this helps.
Try this
SELECT * FROM wp_posts P1
LEFT JOIN wp_postmeta M1 ON (M1.post_id=P1.ID)
WHERE (M1.meta_key = "packageID" and M1.meta_value = 1 )
LEFT JOIN wp_postmeta M2 ON (M2.meta_key=P1.ID AND M2.meta_key = '_thumbnail_id')
LEFT JOIN wp_posts P2 ON (M2.meta_value=P2.ID)
ORDER BY P1.post_date limit 50

Wordpress custom SQL to fecth three posts with given meta values

I have bunch of custom post type footer elements with a meta key footer_element_meta_alignment. Now, I'm trying to fetch three latest posts, which meta_values are 1, 2 and 3. So, one post with each of those values.
How can I achieve this with single SQL Query?
This is my SQL Query so far:
"SELECT wposts.*, meta1.meta_value
FROM $wpdb->posts wposts, $wpdb->postmeta meta1
WHERE 1=1
AND wposts.post_type = 'footer_element'
AND wposts.post_status = 'publish'
AND wposts.ID = meta1.post_id
AND meta1.meta_key = 'footer_element_meta_alignment'
AND (meta1.meta_value = 1 OR meta1.meta_value = 2 OR meta1.meta_value = 3)
ORDER BY meta1.meta_value ASC";
That however fetches all elements with given meta values, and not only the latest one.
ANSWER
Answered my own question.
After struggling few hours I found a solution for this.
SQL
"SELECT *
FROM ( SELECT p.*, m.meta_value AS meta
FROM $wpdb->posts AS p
LEFT JOIN $wpdb->postmeta AS m
ON p.ID = m.post_id
WHERE m.meta_key = 'footer_element_meta_alignment'
AND p.post_status = 'publish'
ORDER BY m.meta_value ASC, p.post_date DESC) AS h
GROUP BY meta";
Fixed (I hope).
SELECT wposts.* FROM $wpdb->posts wposts WHERE
wposts.post_type = 'footer_element'
AND wposts.post_status = 'publish'
AND wposts.ID IN
(SELECT max(meta1.post_id) FROM $wpdb->postmeta meta1
WHERE meta1.meta_value = 1 OR meta1.meta_value = 2 OR meta1.meta_value = 3
GROUP BY meta1.meta_value)