I have a MySQL DB with 2 tables.
First table:
Posts
ID
post_title
post_content
... etc
And second table with additional data:
Postmeta
ID
Post_ID (FK)
meta_key
meta_value
The data that I need is in the meta_key/value pairs. But this DB organized in the way that each row in the second table only have one piece of information.
For example (second table):
ID Post_ID meta_key meta_value
1 5 info 30
ID Post_ID meta_key meta_value
2 5 additional_info 40
ID Post_ID meta_key meta_value
3 6 info 50
ID Post_ID meta_key meta_value
4 6 additional_info 60
So if I run query
SELECT
posts.id,
posts.post_date,
posts.post_author,
posts.post_content,
posts.post_title,
postmeta.meta_id,
postmeta.meta_key,
postmeta.meta_value
FROM posts INNER JOIN postmeta ON posts.id = postmeta.post_id
WHERE posts.post_type = 'post'
I get back all data that I need but data from first table (ID/post_content etc) repeated many times.
But I only need data from first table once but all additional data from second table related to ID from the first table.
How I should filter all this stuff? May be some php loop?
You can use a mysql group_concat function like this:
select
posts.id,
posts.post_date,
posts.post_author,
posts.post_content,
posts.post_title,
group_concat(postmeta.meta_id) as metaID,
group_concat(postmeta.meta_key) as metaKey,
group_concat(postmeta.meta_value_ as metaValue
from
posts
INNER JOIN postmeta
ON posts.id = postmeta.post_id
where
posts.post_type = 'post'
group by
posts.id,
posts.post_date,
posts.post_author,
posts.post_content,
posts.post_title
The to split out the results in PHP you can easily use an explode function to form an array of the resulting information.
SELECT * FROM Posts, Postmeta
WHERE Posts.Post_id = Postmeta.Post_id
GROUP BY Posts.Post_id
Use SELECT DISTINCT instead of just SELECT
Related
I've spent about 4 hours trying to figure out why I cannot do a group by of the post_title and left join the date data from the wp_postmeta table
The code without the group by clause, results all my events but I only want to retrieve the first instance of the event, by grouping by the post_title, which should give me the only first date in the string of classes to sign up for.
What am I doing wrong here?
SELECT posts.post_title,meta.date
FROM wp_posts posts
LEFT JOIN (
SELECT meta_value AS date,post_id FROM wp_postmeta
WHERE wp_postmeta.meta_key ='_EventStartDate'
) meta
ON posts.ID = meta.post_ID
WHERE posts.post_type='Tribe_Events' AND posts.post_status = 'publish'
GROUP BY posts.post_title
Currently meta.date is not in a GROUP BY, no math is performed on this field, and it is not part of a DISTINCT list of fields
It sounds like you want the first instance of wp_postmeta.meta_value for each wp_posts.post_title
If so, try this:
Ditch the subquery and resolve your meta.meta_key filter using COALESCE
Use the MIN function on meta.meta_value
If needed, CAST meta.meta_value as a datetime
Something like this maybe...harder to know without seeing the table structure and sample data.
SELECT posts.post_title
,MIN(CAST(meta.meta_value as DATETIME)) event_start_date
FROM wp_posts posts
LEFT JOIN wp_postmeta meta
ON posts.ID = meta.post_ID
WHERE posts.post_type ='Tribe_Events'
AND posts.post_status = 'publish'
AND COALESCE(meta.meta_key, 'UNKNOWN') ='_EventStartDate'
GROUP BY posts.post_title;
This version can cope with multiple instances of '_EventStartDate' per post_title
Not sure if this is needed but it causes no harm. Just think of it as wearing a belt and suspenders.
I have 4 tables:
posts [post_id post_title post_body post_date post_by post_accepted]
users [user_id user_name user_pw]
comments [comment_id comment_user comment_co comment_post comment_date]
categories [categorie_id categorie_name]
Each table contain a data all data are belong to table posts:
categories<-posts
posts<-users
posts<-comments<-users
I want to get posts with id post_id and get with it a comments and who post it and get the category name and id.
I tried but I get the post but not all comments or if the post does not have comment it will no appear.
This my SQL query:
SELECT COUNT(comment_id),comments.*,categories.*,users.*,posts.*
FROM posts
JOIN categories on (posts.post_id = categories.categorie_id)
JOIN users on (posts.post_by = users.user_id)
LEFT JOIN comments on (posts.post_id = comments.comment_post)
WHERE posts.post_id='34'
AND posts.post_accepted = '1' ;
Try add GROUP BY users.id to your query
I have 3 table
blogposts table, categories table, joins table.
SELECT post_id,
post_title,
post_text,
post_poster,
post_date,
post_slug,
category_name,
user_name
FROM blogposts_categories_join
INNER JOIN blogposts ON post_id = bcj_post_id
INNER JOIN categories ON bcj_category_id = category_id
INNER JOIN users ON post_user = user_id
GROUP BY post_id
This is my query and I want to fetch posts for home page. everything is working but, the fetched data have only one category and I want to make something like this:
Posted in: general, news, health
How must I change my query to get posts, with all categories?
Since you're already grouping by post, you could just use a GROUP_CONCAT to get all the categories, comma separated, something like (the untested);
SELECT post_id,
post_title,
post_text,
post_poster,
post_date,
post_slug,
GROUP_CONCAT(category_name) category_names,
user_name
FROM blogposts_categories_join
INNER JOIN blogposts ON post_id = bcj_post_id
INNER JOIN categories ON bcj_category_id = category_id
INNER JOIN users ON post_user = user_id
GROUP BY post_id
at the end of this I want to display the TITLES of the results that have extra1 as meta_key and test as meta_value.
My goal is to:
From table wp_postmeta get the post_id of every row that has extra1 as meta_key and test as meta_value
Using the post_id, get the post_title for every row on step 1 respectively.
Print the post_title
Thank you very much.
this is the query assuming you are working on wordpress database schema:
SELECT post_title
FROM wp_posts
WHERE ID IN
(
SELECT DISTINCT post_id
FROM wp_postmeta
WHERE meta_key = 'extra1' AND meta_value = 'test'
)
second query after Mairy's comment:
SELECT post_title
FROM wp_posts
WHERE ID IN
(
SELECT DISTINCT post_id
FROM wp_postmeta
WHERE meta_key IN('extra1','extra2','extra3') AND meta_value IN('test','test1','test2','test3')
)
then you just need to loop over th result set with php and then print the post title as you prefer:
//connect to DB then ($query contains the query above)
$res = mysql_query($query, $db);
while($row=mysql_fetch_array($res))
{
echo($row['post_title']);
}
I have a query that creates a table view and then another that queries the view. The results are extremely slow.
Here is the code:
create or replace view $view_table_name as select * from wp_2_postmeta where post_id IN (
select ID FROM wp_2_posts wposts
LEFT JOIN wp_2_term_relationships ON (wposts.ID = wp_2_term_relationships.object_id)
LEFT JOIN wp_2_term_taxonomy ON (wp_2_term_relationships.term_taxonomy_id = wp_2_term_taxonomy.term_taxonomy_id)
WHERE wp_2_term_taxonomy.taxonomy = 'category'
AND wp_2_term_taxonomy.parent = $cat || wp_2_term_taxonomy.term_id = $cat
AND wposts.post_status = 'publish'
AND wposts.post_type = 'post')
The $values have been put it in for this example that queries the view table for the results.
select distinct(ID)
FROM $view_table_name wposts
LEFT JOIN wp_2_postmeta wpostmeta
ON wposts.ID = wpostmeta.post_id
WHERE post_status = 'publish'
AND ID NOT IN (SELECT post_id
FROM wp_2_postmeta
WHERE meta_key = '$var' && meta_value = '$value1')
AND ID NOT IN (SELECT post_id
FROM wp_2_postmeta
WHERE meta_key = '$var' && meta_value = '$value2')
AND ID NOT IN (SELECT post_id
FROM wp_2_postmeta
WHERE meta_key = '$var' && meta_value = '$value3')
AND postmeta.meta_key = 'pd_form'
ORDER BY CASE wpostmeta.meta_value
WHEN '$value5' THEN 1
WHEN '$value6' THEN 2
WHEN '$value7' THEN 3
WHEN '$value8' THEN 4
WHEN '$value9' THEN 5
WHEN '$value10' THEN 6
WHEN '$value11' THEN 7
WHEN '$value11' THEN 8
END;
The main problem here is a subquery in IN condition. Instead executing the subquery and then checking in the outer table for correspondences, MySQL is known to transform the query into a correlated subquery which is executed for each row in the outer table.
The usual solution is to get rid of the subquery in the IN in favour of a JOIN.
Another problem is that you use OUTER JOIN instead of inner JOIN though you do not actually need it (MySQL is usually smart enough to optimize it when it is trivial, but anyway you should express your intention more clearly).
And one more thing. Both queries seem to be dynamically generated. Beside optimizing the query itself, one should think how not to break the calling code. That may be tricky though.
Optimizing wordpress is always an interesting challenge.