Search code examples
mysqlsqlwordpresssql-order-by

MySQL query to get table name with numerically highest number


I have a WordPress multisite database, which has a lot of orphan tables I need to get rid of. The names are structured like this. The number in the table name is the site ID.

wp_9892_wc_booking_relationships
wp_10001_wc_booking_relationships
wp_18992_wc_deposits_payment_plans
wp_20003_followup_coupons
wp_245633_followup_coupon_logs

I want to make a query to find out the highest site ID from the table names.

I've tried queries like this

SELECT table_name FROM information_schema.tables
WHERE table_type = 'base table'
AND table_name REGEXP '^wp_[0-9]+_[a-z0-9]+'
ORDER BY table_name DESC
LIMIT 1; 

But that sorts the results in an unexpected way: I get

wp_9_woocommerce_log

When with LIMIT 10 I see there are names with higher numbers:

wp_99_woocommerce_log
wp_999_woocommerce_log
wp_999_wc_webhooks
wp_999_wc_download_log
wp_999_wcpv_per_product_shipping_rules
wp_999_wcpv_commissions
wp_9999_wcpv_per_product_shipping_rules
wp_9999_wcpv_commissions
wp_9998_wc_points_rewards_user_points_log

Is this something that's doable with a SQL query?


Solution

  • Consider the following data example.

    CREATE TABLE test(
    table_name  varchar(255) );
    
    insert into test values
    ('wp_99_woocommerce_log'),
    ('wp_999_woocommerce_log'),
    ('wp_999_wc_webhooks'),
    ('wp_999_wc_download_log'),
    ('wp_999_wcpv_per_product_shipping_rules'),
    ('wp_999_wcpv_commissions'),
    ('wp_9999_wcpv_per_product_shipping_rules'),
    ('wp_9999_wcpv_commissions'),
    ('wp_9998_wc_points_rewards_user_points_log');
    

    Using,

    SELECT table_name 
    FROM test
    order by (substring_index(substring_index(table_name, 'wp_', -1), '_', 1) * 1 )  desc ;
    

    Will give the following result:

    table_name
    wp_9999_wcpv_per_product_shipping_rules
    wp_9999_wcpv_commissions
    wp_9998_wc_points_rewards_user_points_log
    wp_999_woocommerce_log
    wp_999_wc_webhooks
    wp_999_wc_download_log
    wp_999_wcpv_per_product_shipping_rules
    wp_999_wcpv_commissions
    wp_99_woocommerce_log
    

    https://dbfiddle.uk/590L44Xr

    Using substring_index twice we get the number between wp_ and the second _.

    * 1 is a shortcut to cast the varchar to int.

    In your case it will be something like

    SELECT table_name 
    FROM information_schema.tables
    WHERE table_type = 'base table'
    AND table_name REGEXP '^wp_[0-9]+_[a-z0-9]+'
    ORDER BY  (substring_index(substring_index(table_name, 'wp_', -1), '_', 1) * 1 )   DESC
    LIMIT 1;