DISCLAIMER . The following answer is very long, so I first drew your attention by saying that the query at the end gives the results that match what you want. Here is the SQL Fiddle .
Well, the best way to get closer to this, in my opinion, is to make one requirement at a time.
I want to use only the Prefix and Destination columns of table A.
This is a simple select statement:
SELECT a.prefix, a.destination FROM tableA a;
I want to use only the speed column of table B.
We can add this as easily. Please note that what I have now will simply create a Cartesian product, but it will straighten out as additional requirements are added:
SELECT a.prefix, a.destination, b.rate FROM tableA a, tableB b;
If table prefix A = table B prefix, then copy speed.
I modified the above to use a correlated subquery in the select clause, which pulls the speed if it has a prefix matching the value of tableA. This will result in zero (for now) for any values โโthat do not match:
SELECT a.prefix, a.destination, (SELECT b.rate FROM tableB b WHERE b.prefix = a.prefix) AS rate FROM tableA a;
If the table A prefix is โโnot found in table B, then the copy speed of the prefix in table B starts with the table A prefix (returns only the longest string value).
To do this, I stepped back for a second and wrote a request that receives a bet from B, where the prefix starts with the prefix of table A, forgetting about the previous condition. I used the substring function just like you, but ordered in descending order of length to get the largest:
SELECT a.prefix, a.destination, (SELECT b.rate FROM tableB b WHERE b.prefix = SUBSTRING(a.prefix, 1, LENGTH(b.prefix)) ORDER BY LENGTH(b.prefix) DESC LIMIT 1) AS rate FROM tableA a;
Now you can take this select query and one of them and use the COALESCE function to get the first nonzero value. Thus, those from step 3 that return null values โโwill be replaced by steps 4 (if there is a non-empty value):
SELECT a.prefix, a.destination, COALESCE( (SELECT b.rate FROM tableB b WHERE b.prefix = a.prefix), (SELECT b.rate FROM tableB b WHERE b.prefix = SUBSTRING(a.prefix, 1, LENGTH(b.prefix)) ORDER BY LENGTH(b.prefix) DESC LIMIT 1)) AS rate FROM tableA a;
If the prefix of table A is not in table B, then the copy speed of the prefix in table B, where the prefix of table A begins with the prefix in table B. (returns only the longest string value).
Well, we can do the same as the last, with the exception of manipulating the subquery, to check the opposite tables. In addition, the COALESCE function has no limit in the parameters, so we can simply add it as the third parameter. If the first returns null, it will try the second. If this returns null, it will try to make a third. Here is the final request:
SELECT a.prefix, a.destination, COALESCE( (SELECT b.rate FROM tableB b WHERE b.prefix = a.prefix), (SELECT b.rate FROM tableB b WHERE b.prefix = SUBSTRING(a.prefix, 1, LENGTH(b.prefix)) ORDER BY LENGTH(b.prefix) DESC LIMIT 1), (SELECT b.rate FROM tableB b WHERE a.prefix = SUBSTRING(b.prefix, 1, LENGTH(a.prefix)) ORDER BY LENGTH(a.prefix) DESC LIMIT 1)) AS rate FROM tableA a;
When comparing my results with yours, I noticed that the above does not take into account that both 4 and 5 are satisfied, in which case we want to take the longest prefix. Although there may be a cleaner way to write it, I just wrote the following case statement:
SELECT a.prefix, a.destination, CASE WHEN (SELECT b.rate FROM tableB b WHERE b.prefix = a.prefix) IS NOT NULL THEN (SELECT b.rate FROM tableB b WHERE b.prefix = a.prefix) ELSE CASE WHEN ((SELECT b.rate FROM tableB b WHERE b.prefix = SUBSTRING(a.prefix, 1, LENGTH(b.prefix)) ORDER BY LENGTH(b.prefix) DESC LIMIT 1) IS NOT NULL) AND ((SELECT b.rate FROM tableB b WHERE a.prefix = SUBSTRING(b.prefix, 1, LENGTH(a.prefix)) ORDER BY LENGTH(a.prefix) DESC LIMIT 1) IS NOT NULL) THEN CASE WHEN (SELECT LENGTH(b.prefix) FROM tableB b WHERE b.prefix = SUBSTRING(a.prefix, 1, LENGTH(b.prefix)) ORDER BY LENGTH(b.prefix) DESC LIMIT 1) > (SELECT LENGTH(a.prefix) FROM tableB b WHERE a.prefix = SUBSTRING(b.prefix, 1, LENGTH(a.prefix)) ORDER BY LENGTH(a.prefix) DESC LIMIT 1) THEN (SELECT b.rate FROM tableB b WHERE b.prefix = SUBSTRING(a.prefix, 1, LENGTH(b.prefix)) ORDER BY LENGTH(b.prefix) DESC LIMIT 1) ELSE (SELECT b.rate FROM tableB b WHERE a.prefix = SUBSTRING(b.prefix, 1, LENGTH(a.prefix)) ORDER BY LENGTH(a.prefix) DESC LIMIT 1) END ELSE COALESCE( (SELECT b.rate FROM tableB b WHERE b.prefix = SUBSTRING(a.prefix, 1, LENGTH(b.prefix)) ORDER BY LENGTH(b.prefix) DESC LIMIT 1), (SELECT b.rate FROM tableB b WHERE a.prefix = SUBSTRING(b.prefix, 1, LENGTH(a.prefix)) ORDER BY LENGTH(a.prefix) DESC LIMIT 1)) END END AS rate FROM tableA a;
The logic behind it looks something like this:
- Check if condition 3 is fulfilled.
- Check if conditions 4 and 5 are fulfilled.
- If so, check if the prefix from condition 4 exceeds.
- If so, use this. If this is not the case, use the prefix from condition 5.
- If this is not the case, select the first nonzero condition from conditions 4 and 5.