问题
As context I am running a SQL query in VBA using ACE OLEDB.
The intent of the query is to match dial codes with their destination country. The difficulty is that the match is done not on all digits but to the country code that has the most left matching digits. For example for dial code '7708' it should match to country code '77' (Kazakhstan) but my current code also pulls in '7' (Russia) to the results.
Current query is as follows:
SELECT
TRIM(STR(bcr.DialCode)) as DialCode,
bcr.Destination,
TRIM(STR(cc.CountryCode)) as CountryCode
FROM table1 AS bcr
LEFT JOIN
(
SELECT CountryCode
FROM table2
ORDER BY LEN(CountryCode) DESC
) AS cc
ON cc.CountryCode = LEFT(bcr.DialCode, LEN(cc.CountryCode))
ORDER BY LEN(cc.CountryCode) DESC;
Mock up of schema and query here: http://data.stackexchange.com/stackoverflow/query/679084/left-join-on-longest-match . I had to remove the 'ORDER BY' as it would not accept this command. Don't think it changed the results though. Also had to change TRIM to LTRIM.
As you can see on the results, it doubles each Table1 row for '7' and '77' in the results. Would want only '77' for that particular sample of dial codes. Any guidance is much appreciated. Regards,
回答1:
I've modified your solution from data.stackexchange with following things:
- added length of country code
- changed join condition to
LIKE
matching the pattern - added
row_number
function to properly assign the priority of length matching - added another select statement level to choose those with longest match
rn = 1
Here's the modified query:
SELECT DialCode, Destination, CountryCode
FROM (
SELECT
STR(bcr.DialCode) as DialCode,
bcr.Destination,
LTRIM(STR(cc.CountryCode)) as CountryCode,
row_number() OVER (PARTITION BY bcr.DialCode ORDER BY cc.cc_len DESC) AS rn
FROM @Table1 AS bcr
LEFT JOIN
(
SELECT CountryCode, LEN(CountryCode) AS cc_len
FROM @Table2
) AS cc
ON bcr.DialCode LIKE CONCAT(cc.CountryCode, '%')
) x
WHERE rn = 1
;
回答2:
SELECT
TOP 1 TRIM(STR(bcr.DialCode)) as DialCode,
bcr.Destination,
TRIM(STR(cc.CountryCode)) as CountryCode
FROM table1 AS bcr
INNER JOIN table2 AS cc
ON cc.CountryCode = LEFT(bcr.DialCode, LEN(cc.CountryCode))
WHERE LEN(cc.CountryCode) = MAX(LEN(cc.CountryCode));
来源:https://stackoverflow.com/questions/44295290/left-join-on-longest-match