Mass delete unpopular Tags - wordpress

Mass delete unpopular Tags
I have 1000's of tags and I would like to simply delete all tags that aren't used more than X times... i.e. 5 times.
Does anyone know of a simple way to do this? Even straight SQL would totally ROCK!

Doing with with an SQL command is going to be your best bet. The tables wp_terms, wp_term_relationships, and wp_term_taxonomy are the ones of interest. WordPress keeps track of relationships with wp_term_taxonomy.count. So this help make life easier.
-- remove terms
DELETE FROM wp_terms WHERE term_id IN (SELECT term_id FROM wp_term_taxonomy WHERE taxonomy = 'tag' AND count <= 5;)
-- remove all relationships
DELETE FROM wp_term_relationships WHERE term_taxonomy_id IN (SELECT term_taxonomy_id FROM wp_term_taxonomy WHERE taxonomy = 'tag' AND count <= 5;)
-- remove taxonomy entry
DELETE FROM wp_term_taxonomy WHERE taxonomy = 'tag' AND count <= 5;
Note: I would strongly suggest making a backup of these tables before running the commands above.

Make sure to back up the database first
DELETE a,c FROM wp_terms AS a
LEFT JOIN wp_term_taxonomy AS c ON a.term_id = c.term_id
LEFT JOIN wp_term_relationships AS b on b.term_taxonomy_id = c.term_taxonomy_id
WHERE ( c.taxonomy = 'post_tag' AND c.count <= 5 );
On the last line, you could also modify c.count <= 5 and replace 5 with any number of your choice.

Jasons answer worked except in my install, the name of the taxonomy was 'post_tag' not 'tag'

$x = 5; // set this to any number
$sql = "SELECT `name` FROM `wp_terms`";
$result = mysql_query($sql);
$count = array();
while($row = mysql_fetch_assoc($result))
{
$count[$name]++;
}
foreach($count as $key = $value)
{
if($value < $x)
{
$sql2 = "DELETE FROM `wp_terms` WHERE `name` = '". $key ."'";
$result2 = mysql_query($sql2);
}
}
There's more efficient ways of doing it but this will do the job.
Edit: make a backup first. I'm not entirely sure that that table is exclusive to tags.

Related

Woocommerce and Yoast product search error

I've been trying to use product search in the admin area, it used to work fine, now i get this errors:
SELECT DISTINCT posts.ID as product_id, posts.post_parent as parent_id FROM mu05iq_posts posts
LEFT JOIN mu05iq_wc_product_meta_lookup wc_product_meta_lookup ON posts.ID = wc_product_meta_lookup.product_id
LEFT JOIN mu05iq_wc_product_meta_lookup parent_wc_product_meta_lookup
ON posts.post_type = 'product_variation' AND parent_wc_product_meta_lookup.product_id = posts.post_parent
WHERE posts.post_type IN ('product','product_variation')
AND ( ( ( posts.post_title LIKE '%fiber%') OR ( posts.post_excerpt LIKE '%fiber%') OR ( posts.post_content LIKE '%fiber%' ) OR ( wc_product_meta_lookup.sku LIKE '%fiber%' ) OR ( wc_product_meta_lookup.sku = "" AND parent_wc_product_meta_lookup.sku LIKE '%fiber%' ) ))
ORDER BY posts.post_parent ASC, posts.post_title ASC
WordPress database error: [Unknown column '1' in 'where clause']
SELECT COUNT( 1 ) FROM mu05iq_postmeta WHERE post_id IN( SELECT ID FROM mu05iq_posts WHERE post_type = 'product' ) && meta_value = "1" AND meta_key = '_yoast_wpseo_is_cornerstone'
If anyone has any ideas i would appreciate it.
Thanks and regards.
If someone is experiencing this issue, it's a digital ocean managed database setting, when you create a database cluster it sets up some settings in Global SQL Mode, just remove ANSI_QUOTES. That fixed my issue.

Woocommerce Vendors Set Selling Locations and Manipulate Product Query Loop

I want to only list products that can be shipped to a customer based on their location set in billing/shipping address. (All my users are logged in)
Each of my vendors may ship to certain countries only so I don't want to show products to a user that cannot be shipped to them.
To tackle this problem I have added an extra field in the edit vendor page which saves the countries (via multi select box) they can ship to as a separate term meta.
update_term_meta($term_id, 'vendor_data_shipping_countries', $selected_shipping_countries);
etc...
All that data saves fine and is outputted as follows when I call get_term_meta($term->term_id, 'vendor_data_shipping_countries')[0].
Array
(
[0] => FR
[1] => GB
)
What I am having trouble with now is filtering the product loop query to only show products that can be shipped to the user with the action 'woocommerce_product_query'.
function ac_vendor_show_deliverable_products($query)
{
// magical query filter here...
// if users location matches any of the vendor products ship to countries then output the product to the user
// $query->set(); ... something...
}
add_action('woocommerce_product_query','ac_vendor_show_deliverable_products');
This is where my skill level fails me. I am fairly new to WC and not good at manipulating the query with actions. Better at just writing the full SQL but feel I would mess lots of other things up and filtering is the best way to go.
I expect someone's kunfu is way stronger than mine! Can anyone figure this out?
Hope someone can help.
UPDATE:
I have managed to write exactly what I want to happen in SQL
SELECT SQL_CALC_FOUND_ROWS wp_posts.* FROM wp_posts
LEFT JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
LEFT JOIN wp_term_taxonomy ON (wp_term_taxonomy.term_taxonomy_id = wp_term_relationships.term_taxonomy_id)
LEFT JOIN wp_termmeta ON (wp_termmeta.term_id = wp_term_taxonomy.term_id)
WHERE wp_termmeta.meta_key = 'vendor_data_shipping_countries'
AND wp_termmeta.meta_value LIKE '%"GB"%'
AND wp_posts.post_type = 'product'
AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')
GROUP BY wp_posts.ID
ORDER BY wp_posts.menu_order ASC, wp_posts.post_title ASC LIMIT 0, 12
This only lists products that have added GB as a country they can ship to.
Note the meta_value is stored as a serialized array so the easiest way to match was to perform a LIKE as values are stored as a:2:{i:0;s:2:"FR";i:1;s:2:"GB";} for example.
If anyone can figure out how to put that SQL into the woocommerce_product_query hook then that would be amazing. But I can't for the life of me figure out how this is possible...
Everything on https://codex.wordpress.org/Class_Reference/WP_Query just adds SQL for wp_postmeta not wp_termmeta from what I can see.
Cheers
I managed to get this to work by using the posts_join and posts_where filters instead.
I hope this helps someone else down the line.
/*
* Add the needed term tables
*/
function ac_vendor_sql_join_term_meta($join)
{
global $wp_query, $wpdb;
//only do this is WC product query
if(isset($wp_query->query_vars['wc_query']) && $wp_query->query_vars['wc_query'] == 'product_query')
{
$join .= ' LEFT JOIN '. $wpdb->term_relationships .' tr1 ON (tr1.object_id = '. $wpdb->posts .'.ID)';
$join .= ' LEFT JOIN '. $wpdb->term_taxonomy .' tt1 ON (tt1.term_taxonomy_id = tr1.term_taxonomy_id)';
$join .= ' LEFT JOIN '. $wpdb->termmeta .' tm1 ON (tm1.term_id = tt1.term_id)';
}
return $join;
}
add_filter('posts_join', 'ac_vendor_sql_join_term_meta');
/*
* Add the needed where statements
*/
function ac_vendor_sql_filter_shipping_where($where, $wp_query)
{
//only do this is WC product query
if(isset($wp_query->query_vars['wc_query']) && $wp_query->query_vars['wc_query'] == 'product_query')
{
//get the users billing country code.
if(is_user_logged_in())
{
$billing_country = get_user_meta(get_current_user_id(), 'billing_country', TRUE);
}
else //default to IP location
{
$geo_locate = WC_Geolocation::geolocate_ip($_SERVER['REMOTE_ADDR']);
$billing_country = $geo_locate['country'];
}
$where .= " AND tm1.meta_key = 'vendor_data_shipping_countries'";
$where .= " AND tm1.meta_value LIKE '%\"". $billing_country ."\"%'";
}
return $where;
}
add_filter('posts_where', 'ac_vendor_sql_filter_shipping_where', 10, 2);

wordpress exclude posts from loop if only has one specific category

I have this category which is "community-posts" I don't want it to appear on my homepage loop so I added this to my query
<?php query_posts(array('showposts' => 4,'category__not_in' => $id_communityposts,));?>
This is working fine with me but some "community-posts" I want them to be featured on the homepage loop. (exception)
so I want to only exclude the posts that has one category as "community-posts" if it has this category and more its shows normally.
First thing do not use query_posts - it should never be used as it alter the main query. Use get_posts instead - it's much safer and perform the same task.
To answer your question, let's first imagine how the query would look in SQL (assuming your $id_communityposts is equal to 2) :
SELECT DISTINCT wp_posts.*
FROM wp_posts, wp_postmeta
LEFT JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
LEFT JOIN wp_term_taxonomy ON (wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id)
WHERE
wp_posts.ID = wp_postmeta.post_id AND
(
(wp_term_taxonomy.taxonomy = 'category' AND wp_term_taxonomy.term_id NOT IN(2))
OR
(wp_postmeta.meta_key = 'featured' AND wp_postmeta.meta_value = 1)
)
ORDER BY wp_posts.post_date DESC
LIMIT 4
So we query the post, post meta and taxonomy tables and make two possible conditions:
The category ID is not 2, OR
The featured meta key of the post is set to 1 (change this to whatever key / value depending of how you store the "featured" information).
For that kind of specific cases, get_posts isn't really good to play with - querying the DB with WPDB will give you much more flexibility.
$posts = $wpdb->get_results(
"SELECT DISTINCT $wpdb->posts.*
FROM $wpdb->posts, $wpdb->postmeta
LEFT JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id)
LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)
WHERE
$wpdb->posts.ID = $wpdb->postmeta.post_id AND
(
($wpdb->term_taxonomy.taxonomy = 'category' AND $wpdb->term_taxonomy.term_id NOT IN(2))
OR
($wpdb->postmeta.meta_key = 'featured' AND $wpdb->postmeta.meta_value = 1)
)
ORDER BY $wpdb->posts.post_date DESC
LIMIT 4"
);
Let me know if you run into any issue as it is an untested query.
If I understood the question correctly , The simplest solution, not involving complicated SQL would be something along the lines of :
// NOT TESTED !
if ( count(get_the_category()) > 1 ) { // this means there are more than single category
// show the desired posts
} else {
// dont show
}
read get_the_category() in codex
Along the same logic lines you could also use wp_get_post_categories

Getting the last item from a Drupal db_fetch_object

What's the best way to do this? I've been falling back onto doing a while() loop over the result and snagging the last one as it goes by, but this seems a little, um, inelegant. D7 offers some help here, but is there any advice out there for D6? Thanks!
Why not reverse the order of your query and limit to 1 and get that?
Something like:
$result = db_query_range("SELECT * FROM {table} ORDER BY field DESC", 0, 1);
http://api.drupal.org/api/drupal/includes--database.mysql.inc/function/db_query_range/6
In general case (no engine tips like for mysql), use:
$query = 'SELECT nid, title from {node} WHERE type="page"';
$query_count = 'SELECT count(*) from {node} WHERE type="page"';
$count = db_result(db_query($query_count)); // $query_count
$last_record = db_fetch_object(db_query_range($query, $count-1, 1));
If query use ordering, just use "counter-ordering":
$query = 'SELECT nid, title from {node} WHERE type="page" ORDER BY nid ASC';
// ...
$counterquery = 'SELECT nid, title from {node} WHERE type="page" ORDER BY nid DESC LIMIT 0,1';
$last_record = db_fetch_object(db_query($counterquery));
Try to use db_last_insert_id()

Where does Wordpress store custom menus?

I had to copy a whole wordpress-installation to another server. I simply installed a new Wordpress there and imported all the data from an xml-file previous Wordpress "exported" for me. Anyway, custom menus were not included. Do you know where in the database are they located, so I could grab them from there?
I've got a site with a Magento install and WordPress install sitting next to each other, and cross-linking.
I recently spent several hours writing a class to drop into the Magento installation so that I could render the WordPress menu as the navigation menu in the Magento site.
Posts here have been helpful, but none of them have completely explained the structure of how WordPress menus are stored. Like many WP things, it is stored in a series of relationships. Here's the structure:
(note that this example presumes a table prefix if of "wp_")
First, it's important to recognize that a menu item can be a post (technically it's a page, but pages are stored in the post table), a category, or it can be a custom link.
Because WP supports multiple menus, you first look in the wp_term_taxonomy table table to find any terms with the taxonomy of 'nav_menu'. Note the term_id from that table.
To find the name and slug of the menu, visit the wp_terms table and find the term with the id noted from step 2 above.
Go to wp_term_relationships table and list all of the records with the term_taxonomy_id that matched the term_id from step 1. The object_id field tells you the wp_post.id record where you can find the menu record.
Finally, go to wp_postmeta to find many elements describing the menu. Of particular interest are:
_menu_item_object - the TYPE of menu item (page, custom, or category)
_menu_item_object_id - the id of the actual POST (or category, if it's a category) that the menu item references
_menu_item_menu_item_parent - the heirarchical parent structure of the MENU (which can be different than the post parent relationships)
_menu_item_url - the slug of the menu item (if it is a custom link menu item)
Sample SQL statements to perform the above described operation:
SELECT t.term_id
FROM wp_term_taxonomy as tax
LEFT JOIN wp_terms as t ON tax.term_id = t.term_id
WHERE taxonomy = 'nav_menu' and name like '%top%'
(looks for a menu item with the name of 'Top', and gets the term id)
SELECT p.ID, p.post_title, p.post_name, p.menu_order, n.post_name as n_name, n.post_title as n_title, m.meta_value, pp.meta_value as menu_parent
FROM wp_term_relationships as txr
INNER JOIN wp_posts as p ON txr.object_id = p.ID
LEFT JOIN wp_postmeta as m ON p.ID = m.post_id
LEFT JOIN wp_postmeta as pl ON p.ID = pl.post_id AND pl.meta_key = '_menu_item_object_id'
LEFT JOIN wp_postmeta as pp ON p.ID = pp.post_id AND pp.meta_key = '_menu_item_menu_item_parent'
LEFT JOIN wp_posts as n ON pl.meta_value = n.ID
WHERE txr.term_taxonomy_id = 3 AND p.post_status='publish'
AND p.post_type = 'nav_menu_item' AND m.meta_key = '_menu_item_url'
ORDER BY p.menu_order
(loads the data for the menu, based on the term_id of 3)
Note that this sql statement will work for pages and custom menus (I don't have any categories, so didn't include that). The data loaded will allow you to build the permalink using the siteurl from the wp_options table, and appending the post_name to the end (technically, it's not getting the parent structure, but WP finds the page/post properly without it)
Update
A commenter asked about assembling the child menu items with the parent menu items. That will need to be done with PHP. Something like below will do that for you:
// run the query from above
$results = $wpdb->get_results('SELECT....');
// declare new variable to store "assembled" menu
$menu = array();
// loop over the items assigning children to parents
foreach( $results AS $row ) {
// assemble key bits for the menu item
$item = array(
// handles custom navigation labels
'title' => ( $row->post_title ) ? $row->post_title : $row->n_title,
// handles custom links
'permalink' => ( $row->meta_value ) ? $row->meta_value : get_permalink( $row->ID ),
// declares empty placeholder for any child items
'children' => array()
);
// if the menu item has a parent, assign as child of the parent
if ( $row->menu_parent ) {
$menu[ $row->menu_parent ][ 'children' ][] = $item;
} else {
$menu[ $row->ID ] = $item;
}
}
var_dump( $menu );
// outputs something like below:
/**
* array (size=6)
* 77 =>
* array (size=3)
* 'title' => string 'About Us' (length=8)
* 'permalink' => string 'http://www.example.com/about' (length=33)
* 'children' =>
* array (size=7)
* 0 =>
* array (size=3)
* 'title' => string 'Welcome' (length=22)
* 'permalink' => string 'http://www.example.com/welcome' (length=35)
* 'children' =>
* array (size=0)
* empty
* 1 =>
* array (size=3)
* 'title' => string 'Mission' (length=20)
* 'permalink' => string 'http://www.example.com/mission' (length=33)
* 'children' =>
* array (size=0)
* empty
* 90 =>
* array (size=3)
* 'title' => string 'Contact Us' (length=10)
* 'permalink' => string 'http://www.example.com/contact' (length=33)
* 'children' =>
* array (size=5)
* 0 =>
* array (size=3)
* 'title' => string 'Why Us' (length=12)
* 'permalink' => string 'http://www.example.com/why' (length=35)
* 'children' =>
* array (size=0)
* empty
* 1258 =>
* array (size=3)
* 'title' => string 'Login' (length=12)
* 'permalink' => string 'https://customlink.example.com/some/path/login.php' (length=82)
* 'children' =>
* array (size=0)
* empty
*/
For people still arriving at this question, I'll put it in simple phpMyAdmin terms.
There are 6 tables involved.
1. wp_term_taxonomy
WordPress keeps each nav menu location as a record in the 'wp_term_taxonomy' table, but the only unique identifier there is a number ID; 1, 2, 3, etc.
You can also see the 'count' figures that show the number of items in each menu location.
This is what's created when you type
register_nav_menu('your-navmenu', 'Your Navmenu');
You will not find the name 'Your Navmenu' anywhere in the database – that is just used for labelling it in the interface.
However, you will find 'your-navmenu' elsewhere.
2. wp_terms
Your actual menus get stored in 'wp_terms'.
WordPress is confusing with this terminology. In the interface, it has 'display locations' and 'menus'. The location is what's created by register_nav_menu(). It's best to consider the 'menus' in the interface as lists of pages.
I've given them the name 'navlist' here.
The menus also get their own IDs, which are often the same as the location IDs (because people often create one menu for one location at the same time), which can get confusing.
This item is created by the 'Menus' page in the admin interface:
3. wp_options
You will see the 'your-navmenu' slug in 'wp_options'. Here, WordPress stores your current settings for the nav menus. It stores it in a serialised array (using PHP's serialize() function).
The original array (obtained using unserialize()) looks like this.
array (
'custom_css_post_id' => 56,
'nav_menu_locations' =>
array (
'your-navmenu' => 2,
'another-navmenu' => 3,
),
)
This changes according to which menu (by its ID; '2', '3') you set to which location (by its slug; 'your-navmenu', 'another-navmenu').
4. wp_posts
The menu entries themselves are stored in a different table, 'wp_posts'.
You can find these by searching for 'nav_menu_item':
I've cut out most of the columns for brevity and kept the relevant ones.
Here, you can see the 'menu_order' column, which stores their order in the menu they are in.
The menu entries are stored like actual posts, with a post ID and URL (but it will bring a 404 if you visit it, and they have no 'post_content').
All menu items stored as a sub-item will have a 'post_parent' ID. This is the ID of the actual page that their parent links to, not its menu item ID.
5. wp_postmeta
Menu items are linked to their respective pages in the 'wp_postmeta' table.
The menu item ID ('post_id') is stored in relation to the post ID ('meta_value') in the '_menu_item_object_id' rows, while sub-items are linked to their parent items in the '_menu_item_menu_item_parent' rows.
It's easy to get confused here.
'post_id' is the ID of the menu item, not the post. 'meta_value' is the ID of the post, not the menu item, in '_menu_item_object_id' rows, but it's the ID of the parent menu item, not a post, in '_menu_item_menu_item_parent' rows.
6. wp_term_relationships
The links between each menu item and each menu location are stored in 'wp_term_relationships'.
Here, 'object_ID' is the post ID of the menu item (as seen in 'wp_posts'), and 'term_taxonomy_id' is the ID of the menu location (as seen in 'wp_term_taxonomy').
Hope this cleared it up for some people. I know I was very confused at the start.
I found this just because I was looking for the answer myself.
I see your post is quite old, but the answer is in wp_postmeta, run this query:
SELECT *
FROM `wp_postmeta`
WHERE meta_key LIKE '%menu%'
LIMIT 0, 30
You'll find many entries.
This setting happens in the wp_posts table.
Look in the table for records where the menu_order greater than zero.
select * from wp_posts where menu_order > 0;
It will also give you the name of the option in the wp_options table where the menu option is configured.
select * from wp_options where option_name = "nav_menu_options";
Also be aware that that wordpress import/export tool will not import media (images,video etc) from the media library which are not being used in posts. If you've got stuff that you directly linked to, its not going to be moved either.
I have been searching high and low for the entire structure and I finally cracked the code:
SELECT
p.ID,
m.meta_value,
md.post_author,
wp_users.user_nicename,
p.post_parent,
p.menu_order,
md.post_title
FROM
wp_posts AS p
INNER JOIN wp_postmeta AS m ON m.post_id = p.ID
INNER JOIN wp_posts AS md ON md.ID = m.meta_value AND m.meta_value = md.ID
INNER JOIN wp_users ON md.post_author = wp_users.ID
WHERE
p.menu_order > 0 AND
p.post_type = 'nav_menu_item' AND
m.meta_key = '_menu_item_object_id'
ORDER BY
p.menu_order ASC
To simplify/complexify #random_user_name's two queries, you can condense them into 1 query so that the only input parameter needed is the menu name. Like this:
SELECT p.ID, p.post_title, p.post_name, p.menu_order,
n.post_name as n_name, n.post_title as n_title,
m.meta_value, pp.meta_value as menu_parent
FROM wp_term_taxonomy as tax
INNER JOIN wp_terms as t ON tax.term_id = t.term_id
INNER JOIN wp_term_relationships as txr ON t.term_id = txr.term_taxonomy_id
INNER JOIN wp_posts as p ON txr.object_id = p.ID AND p.post_status = 'publish' AND p.post_type = 'nav_menu_item'
LEFT JOIN wp_postmeta as m ON p.ID = m.post_id AND m.meta_key = '_menu_item_url'
LEFT JOIN wp_postmeta as pl ON p.ID = pl.post_id AND pl.meta_key = '_menu_item_object_id'
LEFT JOIN wp_postmeta as pp ON p.ID = pp.post_id AND pp.meta_key = '_menu_item_menu_item_parent'
LEFT JOIN wp_posts as n ON pl.meta_value = n.ID
WHERE tax.taxonomy = 'nav_menu'
AND t.name like '%main nav%'
ORDER BY p.menu_order
This SQL statement gets the job done a little more thoroughly and legibly than the rest, I think. All you need to do is put your menu name into t.name = 'main nav' on the first join. It outputs every tidbit of menu info except the XFN field.
SELECT t.name as 'menu name',
p1.ID as 'post id', p1.post_title as title, p1.post_name as slug, p1.menu_order as 'order',
m1.meta_value as classes, m2.meta_value as menu_item_parent, m3.meta_value as object, m4.meta_value as object_id,
m5.meta_value as target, m6.meta_value as type, m7.meta_value as url,
p2.post_title as 'title-2', p2.post_name as 'slug-2'
FROM wp_term_taxonomy as tax
INNER JOIN wp_terms as t ON t.term_id = tax.term_id AND t.name = 'main nav'
INNER JOIN wp_term_relationships as txr ON txr.term_taxonomy_id = t.term_id
INNER JOIN wp_posts as p1 ON p1.ID = txr.object_id AND p1.post_status = 'publish' AND p1.post_type = 'nav_menu_item'
LEFT JOIN wp_postmeta as m1 ON m1.post_id = txr.object_id AND m1.meta_key = '_menu_item_classes'
LEFT JOIN wp_postmeta as m2 ON m2.post_id = txr.object_id AND m2.meta_key = '_menu_item_menu_item_parent'
LEFT JOIN wp_postmeta as m3 ON m3.post_id = txr.object_id AND m3.meta_key = '_menu_item_object'
LEFT JOIN wp_postmeta as m4 ON m4.post_id = txr.object_id AND m4.meta_key = '_menu_item_object_id'
LEFT JOIN wp_postmeta as m5 ON m5.post_id = txr.object_id AND m5.meta_key = '_menu_item_target'
LEFT JOIN wp_postmeta as m6 ON m6.post_id = txr.object_id AND m6.meta_key = '_menu_item_type'
LEFT JOIN wp_postmeta as m7 ON m7.post_id = txr.object_id AND m7.meta_key = '_menu_item_url'
LEFT JOIN wp_posts as p2 ON p2.ID = m4.meta_value AND p2.post_status = 'publish' AND m6.meta_value = 'post_type'
WHERE tax.taxonomy = 'nav_menu'
ORDER BY p1.menu_order
I added additional column on cale_b's query. The column lvl has depth for indentation.
Assume that:
max depth is 6, so i defined 6 variables.
menu's post_id is over 6. Most of you would've already exceed that number.
Query:
select case when a.meta_value = 0 then least(#lvl:=1, #p1:=a.id)
when a.meta_value = #p1 then least(#lvl:=2, #p2:=a.id)
when a.meta_value = #p2 then least(#lvl:=3, #p3:=a.id)
when a.meta_value = #p3 then least(#lvl:=4, #p4:=a.id)
when a.meta_value = #p4 then least(#lvl:=5, #p5:=a.id)
when a.meta_value = #p5 then least(#lvl:=6, #p6:=a.id)
end lvl
,a.id
from (
SELECT p.id
,p.post_title
,p.post_name
,pp.meta_value
,p.menu_order
,n.post_name as n_name
,n.post_title as n_title
,m.meta_value meta2
FROM wordpress_dw.stat_term_relationships as txr
INNER JOIN wordpress_dw.stat_posts as p ON txr.object_id = p.ID
LEFT JOIN wordpress_dw.stat_postmeta as m ON p.ID = m.post_id and m.meta_key = '_menu_item_url'
LEFT JOIN wordpress_dw.stat_postmeta as pl ON p.ID = pl.post_id AND pl.meta_key = '_menu_item_object_id'
LEFT JOIN wordpress_dw.stat_postmeta as pp ON p.ID = pp.post_id AND pp.meta_key = '_menu_item_menu_item_parent'
LEFT JOIN wordpress_dw.stat_posts as n ON pl.meta_value = n.ID
,(select #lvl:=0, #p1:=0, #p2:=0, #p3:=0, #p4:=0, #p5:=0, #p6:=0) x
WHERE txr.term_taxonomy_id = 2 -- your menu term id
AND p.post_status='publish'
AND p.post_type = 'nav_menu_item'
ORDER BY p.menu_order
) a
Result:
lvl |id |
----|----|
1 |508 |
1 |509 |
2 |510 |
3 |511 |
3 |512 |
3 |513 |
3 |514 |
2 |515 |
1 |516 |
2 |517 |
2 |518 |
3 |519 |
3 |520 |
3 |521 |
3 |522 |

Resources