Left Join on Longest Match

烂漫一生 提交于 2019-12-12 07:03:42

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!