I created a custom post type : stock
In stock, I have add a lot of custom field with ACF.
I created maybe 20 stock.
Now, I'm trying to get the values of the different custom field (in workbench) for each post.
Here some field : prix (price), ville (city), nombre de chambres (number of rooms)
The result I want :
post_title | prix | ville | nombre de chambres
Title 1 | 20 | paris | 3
Title 2 | 40 | marseille| 4
Title 3 | 30 | royan| 2
etc...
The code I tried :
SELECT post_title,
(select meta_value from mod803_postmeta where meta_key = 'prix')
FROM mod803_posts
WHERE post_type='stock' AND post_status='publish'
I get the title and a column named : "select meta_value from mod803_postmeta where meta_key = 'prix'" but the column is 'NULL'.
Thank you
So, here the solution for get WP POST with CUSTOM POST TYPE AND ACF FIELDS :
SELECT ID, p.post_title as 'Post Title', t.name as 'Category', p.post_date as
"Post Date", p.post_name as "Post Name" , m2.meta_value AS "Prix", m4.meta_value
AS "Surface"
FROM mod803_posts p, mod803_terms t, mod803_term_relationships tr,
mod803_term_taxonomy tx, mod803_postmeta m2, mod803_postmeta m4
WHERE p.post_type = 'stock'
AND p.post_status = 'publish'
AND tx.taxonomy = 'typedestock'
AND p.ID = tr.object_id
AND tr.term_taxonomy_id = t.term_id
AND tx.term_id = t.term_id
AND m2.post_id = p.id AND m2.meta_key = 'Prix de vente'
AND m2.post_id = p.id AND m4.meta_key = 'Surface'
Related
Using the following tables:
post_meta
-----
meta_id post_id key value
-----
22 4546 Advantages old value
23 4546 Article number 123
posts
-----
id status
-----
4546 pending
4547 publish
4548 publish
I am trying to write an UPDATE query to change 'old value' to 'new value', for posts that are set 'pending' which id corresponds to post_meta's post_id that has 'Article number' set to '123'.
I have no idea how to proceed ... any ideas?
If your intent is to change the value of the row with meta_key = 'Advantages' from 'old value' to 'new value' for the rows with meta_key = 'Article' and value = '123' for which there exists a corresponding post_id in posts with status = 'Pending' then I think the query you want is this:
update post_meta
join (
select pm.meta_id
from post_meta pm
join posts p on pm.post_id = p.id
where p.status = 'pending'
and pm.`key` = 'Advantages' -- or pm.value = 'old value'
and exists (
select 1
from post_meta
where post_id = pm.post_id
and `key` = 'Article number' and value = '123')
) t on post_meta.meta_id = t.meta_id
set value = 'new value';
Sample SQL Fiddle
With your sample data this would leave the post_meta table looking like this:
| meta_id | post_id | key | value |
|---------|---------|----------------|-----------|
| 22 | 4546 | Advantages | new value |
| 23 | 4546 | Article number | 123 |
Updated query
UPDATE post_meta pm, (
SELECT pm2.meta_id
FROM posts p
INNER JOIN post_meta pm1 ON p.id=pm1.post_id
INNER JOIN post_meta pm2 ON p.id=pm2.post_id
WHERE
pm1.key='Article Number' AND pm1.value = 123
AND pm2.key='Advantages' AND pm2.value = 'old value'
AND p.status = 'pending'
) p
SET pm.value = 'new value'
WHERE pm.meta_id=p.meta_id
Despite Googling this for 2 hours and trying a variety of JOINS and UNIONS and ALIASES and whatnot, I still can't retrieve in one table the result of two subqueries in the wp_postmeta table from the WordPress database (I don't even care about wp_posts here, all the data I'm interested in is in postmeta).
I have custom fields (managed with the ACF plugin) that look like the following in the database, with one key for regions and another for a numeric value.
| ID | meta_key | meta_value |
| 1 | group_name | Japan |
| 1 | facility_index | 0.83 |
| 2 | group_name | USA |
| 2 | facility_index | 4.51 |
I need a query that returns the following so that I can calculate aggregates by region (for instance, the sum of facility_index for all facilities, by country/region, i.e. by group_name):
| ID | group_name | facility_index |
| 1 | Japan | 0.83 |
| 2 | USA | 4.51 |
This query lists group_name twice instead of listing facility_index in the 3rd column:
SELECT post_id, meta_value, result2.meta_value FROM
(
(
SELECT post_id, meta_value
FROM wp_postmeta
WHERE meta_key = "group_name"
)
UNION
(
SELECT post_id, meta_value
FROM wp_postmeta
WHERE meta_key = "facility_index"
)
) AS result2
GROUP BY post_id
Edit to display the final query that does exactly what I wanted, thanks to the accepted answer below:
SELECT
meta1.meta_value AS group_name,
meta2.meta_value AS facility_index,
SUM(meta2.meta_value) AS 'fac_index_geo'
FROM wp_posts post
LEFT JOIN wp_postmeta meta1 ON meta1.post_id = post.ID AND meta1.meta_key = 'group_name'
LEFT JOIN wp_postmeta meta2 ON meta2.post_id = post.ID AND meta2.meta_key = 'facility_index'
WHERE
post.post_type = 'facility'
GROUP BY group_name
As I understand you are looking for a custom SQL query - i.e. you don't want to use a WP_Query object.
For this I'd use some JOINS instead of subqueries.
Also I encourage you to query for the post_type, as otherwise you might get data from autosaves/revisions or similar wrong results.
/*
INNER JOIN
This query will only return posts that contain all meta values
i.e. all 'post' items with group_name AND facility_index
*/
$sql = "
SELECT
post.ID,
meta1.meta_value AS group_name,
meta2.meta_value AS facility_index
FROM {$wpdb->posts} post
INNER JOIN {$wpdb->postmeta} meta1 ON meta1.post_id = post.ID AND meta1.meta_key = 'group_name'
INNER JOIN {$wpdb->postmeta} meta2 ON meta2.post_id = post.ID AND meta2.meta_key = 'facility_index'
WHERE
post.post_type = 'post'
";
$data = $wpdb->get_results( $sql );
Just make sure to update the post_type condition to match your required post type.
Alternatively you can use this query if you want to also get posts that have a missing meta value
/*
LEFT JOIN
This query will return all posts even if they have missing meta values
i.e. if group_name or facility_index is empty, then NULL is returned in the column
*/
$sql = "
SELECT
post.ID,
meta1.meta_value AS group_name,
meta2.meta_value AS facility_index
FROM {$wpdb->posts} post
LEFT JOIN {$wpdb->postmeta} meta1 ON meta1.post_id = post.ID AND meta1.meta_key = 'group_name'
LEFT JOIN {$wpdb->postmeta} meta2 ON meta2.post_id = post.ID AND meta2.meta_key = 'facility_index'
WHERE
post.post_type = 'post'
";
I have to fetch title, description and attachment out of the wordpress database without wp_query. I can't get how to fetch both, attachments and meta_descriptions at the same time...
This is how my query looks like so far
$query="SELECT post_title, meta_value
FROM wp_posts p JOIN wp_postmeta pm ON p.ID=pm.post_id
WHERE post_status='publish'
AND post_type='page'
AND post_parent=2330
AND ( meta_key='_wpseo_edit_description' OR meta_key='_wp_attached_file' )
ORDER BY post_date DESC";
This query returns "doubled" results i have to split within a loop
______________________________
| post_title | meta_value |
|------------|---------------|
| title 1 | 1349 |
|------------|---------------|
| title 1 | description 1 |
|------------|---------------|
| title 2 | 1348 |
|------------|---------------|
| title 2 | description 2 |
|____________|_______________|
You wlil need to join onto the wp_postmeta table in order to get any of the attached information, such as file attachments or custom fields.
An example of how to do this:
SELECT p.*, pm2.meta_value AS featured_image, pm3.meta_value AS wpseo_edit_description, pm4.meta_value AS wp_attached_file
FROM `wp_posts` p
LEFT JOIN `wp_postmeta` pm2 ON p.ID = pm2.post_id AND pm2.meta_key = 'wp_attached_file'
LEFT JOIN `wp_postmeta` pm3 ON p.ID = pm3.post_id AND pm3.meta_key = '_wpseo_edit_description'
LEFT JOIN `wp_postmeta` pm4 ON p.ID = pm4.post_id AND pm4.meta_key = '_wp_attached_file'
WHERE p.post_status = 'publish'
AND p.post_type = 'page'
AND p.post_parent = 2330
The normal post fields (post title, description, ID, etc) will then be available, along with featured_image, wp_attached_file and wpseo_edit_description.
I have 2 tables - posts and postmeta.
posts
ID title category post_status post_type
1 ABC cat-1 Publish Store
2 DEF cat-2 Publish Store
3 GHI cat-3 Publish Store
4 JKL cat-2 Publish Store
5 XYZ cat-5 Draft Store
6 MNO cat-9 Publish Article
and
postmeta
meta_id post_id meta_key meta_value
109 1 city 1
110 1 featured h
111 2 city 1,2
112 2 featured both
113 3 city 2,3
114 3 featured both
115 4 city 1
116 4 featured n
117 5 city 1,4
118 5 featured h
119 6 city 1
120 6 featured h
I am trying to run a query that would give me a list of posts which has the following conditions:
Whose value against city has 1 AND
whose value for featured is either h or both AND
whose post status is Publish AND
whose post type is Store
Order them by title
The query I am trying is
SELECT DISTINCT posts.ID , posts.*, postmeta.*
FROM posts, postmeta
WHERE posts.ID = postmeta.post_id
AND (postmeta.meta_value = 'h' OR postmeta.meta_value = 'both')
AND (postmeta.meta_key = 'post_city_id' AND (postmeta.meta_value LIKE '%,1,%' OR postmeta.meta_value LIKE '%1,%' OR postmeta.meta_value LIKE '%,1%' OR postmeta.meta_value LIKE '%1%'))
AND posts.post_status = 'Publish'
AND posts.post_type = 'Store'
ORDER BY (SELECT postmeta.meta_value from postmeta where (posts.ID = postmeta.post_id) and postmeta.meta_key LIKE '%home_featured_type%') asc, posts.post_title LIMIT 0,6
The correct returns would be IDs 1 and 2 i.e. abc and def. But I am getting empty result. I cannot figure out where it is falling apart. How can this be fixed?
here is a fixed query, but I still don't understand the mysterious ORDER BY (SELECT) thingie.
http://sqlfiddle.com/#!2/5ce5a/19
SELECT DISTINCT posts.ID , posts.*, postmeta_city.*, postmeta_featured.*
FROM posts
INNER JOIN postmeta AS postmeta_city
ON postmeta_city.post_id = posts.ID
AND postmeta_city.meta_key = 'city'
AND ( postmeta_city.meta_value LIKE '%,1,%'
OR postmeta_city.meta_value LIKE '%1,%'
OR postmeta_city.meta_value LIKE '%,1%'
OR postmeta_city.meta_value LIKE '%1%'
)
INNER JOIN postmeta AS postmeta_featured
ON postmeta_featured.post_id = posts.ID
AND postmeta_featured.meta_key = 'featured'
AND ( postmeta_featured.meta_value = 'h'
OR postmeta_featured.meta_value = 'both'
)
WHERE posts.post_status = 'Publish'
AND posts.post_type = 'Store'
ORDER BY (
SELECT postmeta.meta_value
FROM postmeta
WHERE ( posts.ID = postmeta.post_id )
AND postmeta.meta_key LIKE '%home_featured_type%'
) asc,
posts.title
LIMIT 0,6;
;
Updated with other people's ideas, please upvote them:
http://sqlfiddle.com/#!2/5ce5a/33
SELECT DISTINCT posts.ID , posts.*, postmeta_city.*, postmeta_featured.*
FROM posts
INNER JOIN postmeta AS postmeta_city
ON postmeta_city.post_id = posts.ID
AND postmeta_city.meta_key = 'city'
AND FIND_IN_SET('1', postmeta_city.meta_value)
INNER JOIN postmeta AS postmeta_featured
ON postmeta_featured.post_id = posts.ID
AND postmeta_featured.meta_key = 'featured'
AND postmeta_featured.meta_value IN ('h','both')
WHERE posts.post_status = 'Publish'
AND posts.post_type = 'Store'
ORDER BY (
SELECT postmeta.meta_value
FROM postmeta
WHERE ( posts.ID = postmeta.post_id )
AND postmeta.meta_key LIKE '%home_featured_type%'
) asc,
posts.title
LIMIT 0,6;
;
You're getting an empty result set because you are ANDing the meta_value column so it has to equal two values at the same time which is impossible. Something like val = '1' AND val = 'both' will always return false and none of the rows would join. Instead, you must use an OR between conditions: city -> 1 and featured -> h/both.
Since the post must contain both city -> 1 and featured -> h/both (which are not across columns but across multiple rows), you'll need a HAVING clause in conjunction with a GROUP BY to ensure each post joins with two rows, satisfying both conditions... not one or the other.
Also, that is an awful lot of LIKE's to check for the existance of a 1. You can use FIND_IN_SET instead:
SELECT
*
FROM
posts a
INNER JOIN
postmeta b ON a.ID = b.post_id
AND
(
(b.meta_key = 'city' AND FIND_IN_SET('1', b.meta_value) > 0)
OR
(b.meta_key = 'featured' AND b.meta_value IN ('h', 'both'))
)
WHERE
a.post_status = 'Publish'
AND a.post_type = 'Store'
GROUP BY
a.ID
HAVING
COUNT(*) = 2
ORDER BY
a.title
Try this :
SELECT DISTINCT posts.ID , posts.*, postmeta.*
FROM posts AS p INNER JOIN postmeta AS pm
WHERE p.ID = pm.post_id
AND (pm.meta_value in ('h','both')
AND (pm.meta_key = 'city' AND
(pm.meta_value LIKE '%,1,%' OR pm.meta_value LIKE '%1,%' OR pm.meta_value LIKE '%,1%' OR pm.meta_value LIKE '%1%'))
AND posts.post_status = 'Publish'
AND posts.post_type = 'Store'
ORDER BY p.title LIMIT 0,6
Since you want order by title only, so there is no need to write any query in 'order by' clause.
I need to do select from Post table, each post is related to one category and on tag.
I need to select specific tag/s and/or category/s.
Terms table have custom field "menu_order", it is used to set category order.
I want to sort posts by that field.
If i do plain select:
SELECT * from wp_posts
LEFT
JOIN wp_term_relationships
ON ( wp_term_relationships.object_id = wp_posts.ID )
LEFT
JOIN wp_terms
ON ( wp_terms.term_id = wp_term_relationships.term_taxonomy_id )
WHERE 1=1
AND wp_posts.post_type = 'post'
AND (
wp_posts.post_status = 'publish'
OR wp_posts.post_status = 'private'
)
LIMIT 0, 20
I get result:
+----------------+----------------+----------+---------------------+
| POST ID | Term name | order | type |
+----------------+----------------+----------+---------------------+
| 2 | Fire | 1 | category |
+----------------+----------------+----------+---------------------+
| 2 | blue | 0 | tag |
+----------------+----------------+----------+---------------------+
That is just the intro.
If I do WHERE $wpdb->terms.term_id = 170 what is a TAG I have only one return.
+----------------+----------------+----------+---------------------+
| POST ID | Term name | order | type |
+----------------+----------------+----------+---------------------+
| 2 | blue | 0 | tag |
+----------------+----------------+----------+---------------------+
I need to select POSTS, filter out by category or/and tag, then get TERM_ORDER from category attached to POST.
So, no matter what results I have, order is always pulled from related category.
As I am not so strong in MYSQL, this gets me baffled. Any input would be helpful :)
UPDATE --------------------------------------------------
So, after crazy coding I managed to get what I wanted.
Do not hold your breath as this probably is ugly and slow, but works.
First, I create view where all products are collected.
$qqquery = "
CREATE VIEW samsam AS
SELECT
ID, post_content, post_title, post_excerpt, post_status, post_name, guid, post_type, $wpdb->term_relationships.term_taxonomy_id as cat_term_taxonomy_id, tt1.term_taxonomy_id as tag_term_taxonomy_id
FROM $wpdb->posts
LEFT
JOIN $wpdb->term_relationships
ON ( $wpdb->term_relationships.object_id = $wpdb->posts.ID )
LEFT
JOIN $wpdb->term_relationships AS tt1
ON ( tt1.object_id = $wpdb->posts.ID )
WHERE 1=1
AND $wpdb->posts.post_type = 'post'
AND (
$wpdb->posts.post_status = 'publish'
OR $wpdb->posts.post_status = 'private'
)
AND ( wp_term_relationships.term_taxonomy_id IN ( $query_cat ) // ID's of categories, seperated by coma
AND tt1.term_taxonomy_id IN (' . $add_query_tag_id . ') //ID's of POSTS seperated by coma
)
ORDER BY $wpdb->term_relationships.term_taxonomy_id DESC
";
$wpdb->query($qqquery);
After that I do query where I select view and join relationships and terms to get category order by filtering out order > 0, then group BY id to filter out duplicates.
$querystr = "
SELECT * from samsam
LEFT
JOIN $wpdb->term_relationships
ON (samsam.ID = $wpdb->term_relationships.object_id)
LEFT
JOIN $wpdb->terms
ON ($wpdb->terms.term_id = $wpdb->term_relationships.term_taxonomy_id)
AND ($wpdb->terms.menu_order > 0)
WHERE menu_order > 0
GROUP BY ID
ORDER BY menu_order ASC
LIMIT $item_limit_offset, $item_limit_pp"; // first is calculation of products to skip, second is how many posts per page
$pageposts = $wpdb->get_results($querystr, OBJECT);
What it does:
Category 1 (have order 1)
post
post
post
Category 3 (have order 2)
post
post
post
Category 2 (have order 3)
post
post
post
Can be limited, offseted, paginated, filtered out by tags and/or categories.
I used plugin "Term Menu Order" that adds extra field to order categories.
Have a nice day.
Why are you writing your own query here? Wordpress has built in functions to retrieve data.
http://codex.wordpress.org/Template_Tags/get_posts
http://codex.wordpress.org/Function_Reference/query_posts