0

I use Wordpress/Woocommerce with MySQL. I need to find all orders with the same billing phone as a given one. The basic SQL is below. The problem is that when the phone numbers were stored in the DB they were not canonized and so there are all possible forms like 0YZ-abcd, 0YZabcd,+KMYZabcs, etc I already have a PHP function to canonize any phone number. My question is how to apply that function to every row's _billing_phone column which is being considered in the WHERE clause.

The original SQL is

 $canonized_phone_to_compare_to = canonize_phone_number($original_phone_number);

 $results = $wpdb->get_col( "
    SELECT p.ID FROM {$wpdb->prefix}posts AS p
    INNER JOIN {$wpdb->prefix}postmeta AS pm ON p.ID = pm.post_id
    WHERE pm.meta_key = '_billing_phone' 
    AND pm.meta_value = '" . $canonized_phone_to_compare_to . "'      
" );

What I need is to find a way to apply canonize_phone_number() to pm.meta_value just before it gets compared. In other words, each time the SQL 'checks' if the pm.meta_value equals to $canonized_phone_to_compare_to I want the SQL to apply my function (or a stored procedure maybe?) to pm.meta_value and re-format that field

Or any other way to tackle this?

Louis Shraga
  • 773
  • 1
  • 7
  • 26

2 Answers2

1

You can't run a PHP function in a running SQL-query. I think the best would be if you stored them in a universal format.

Depending on how you're data is stored you could use replace to get rid of white-spaces and minus sign. Then use right function to get the last part from your phone numbers. I don't recommend this because you won't be able to index and the query could become slow. (It's not the case for newer versions of MySQL.)

For example, in Sweden, all mobile numbers look like this 07z-xxx xx xx, 00467z-xxx xx xx, +467z-xxxxxxx, +46(0)7z-xx xx xxx. In this case, you could replace all white-spaces and minus sign with nothing, then match on the last 7 digits.

All countries have their numbering plan so you've to check the documentation for your data.

mikaelwallgren
  • 310
  • 2
  • 9
  • could you please elaborate a bit more on your _"you won't be able to index and the query could become slow"_. In which case is that and why? Do you mean this will happen if I replace the numbers in the DB? thanks – Louis Shraga Apr 28 '20 at 14:58
  • My bad, with newer versions you're able to index with a functional key. Please see [this post](https://stackoverflow.com/a/35380963/13405589). This was only meant if you didn't want to transform all your existing and future numbers. – mikaelwallgren Apr 28 '20 at 21:09
  • @mikaelwallgren- having a function as they key is a cool piece of info to discover for me about MySQL, thanks! Unfortunately, since the DB "belongs" to the WordPress instance, I am not sure I would/can change such things. But I am trying to better understand your answer. You started the paragraph with a suggestion to replace the existing data by re-formatted data. Why would I need a functional key in this case? Since I am considering to go and replace all data, I am worried I miss something related to what you said – Louis Shraga Apr 29 '20 at 21:44
  • If you're replacing your data to a universal format you won't need a functional key index. – mikaelwallgren Apr 30 '20 at 06:38
1

i'm not sure about SQL but you can always do it in PHP . so try getting the columns without the last part .

surely there is better way to do it but I think this will work .

$canonized_phone_to_compare_to = "0xxxxxxxxxx";
$results = $wpdb->get_col("
    SELECT p.ID FROM {$wpdb->prefix}posts AS p
    INNER JOIN {$wpdb->prefix}postmeta AS pm ON p.ID = pm.post_id
    WHERE pm.meta_key = '_billing_phone'   
 ");
foreach ($results as $i => $v) {
    $results[$i]['pm.meta_value'] = canonize_phone_number($results[$i]['pm.meta_value']);
    if ($canonized_phone_to_compare_to == $results[$i]['pm.meta_value']) {
        $newResults[] = $results[$i];
    }
}
Abolfazl Ghaemi
  • 424
  • 2
  • 14
  • @ag thanks but that will be awfully slow in my use-case. This query will fetch thousands of numbers each time and run for thousands times each time the user opens the orders admin page of the site. If no good answer here i will make a stores procedure in the DB probably – Louis Shraga Apr 28 '20 at 00:33
  • 1
    @LouisShraga I think the best way to fix this is just make a UPDATE query . change all of numbers to one type of format , then it's just easy to use . – Abolfazl Ghaemi Apr 28 '20 at 11:45
  • @AbolfaziGhaemi - yep, not just that but I also need to make sure all new entries are brought to the same format as well before stored... Probably this is what I am going to do – Louis Shraga Apr 28 '20 at 14:53