Mysql 从 dns 域名中提取 tld 的查询

Mysql query to extract tld from dns domain names

在这个练习中,我想从 TLD(顶级域)中提取域名,给出以下 tables。

Table name: dns
+---------------------------+
| dnsdomain                 |
+---------------------------+
| ns2.hosting.indo.net.id.  |
| ns1.onepanel.indo.net.id. |
| ns-1591.awsdns-06.co.uk.  |
| mail189.atl21.rsgsv.net.  |
| gli.websitewelcome.com.   |
| ns2.metrolink.pl.         |
| ns1.metrolink.pl.         |
| ns-1591.awsdns-06.co.uk.  |
| NS3.METRORED.HN.          |
| NS.METRORED.HN.           |
| ns2.hosting.indo.net.id.  |
| ns1.onepanel.indo.net.id. |
| www.csis.ul.ie.           |
+---------------------------+
and 
Table name: tld
+----------+
| tld      |
+----------+
| .net.id. |
| .co.uk.  |
| .net.    |
| .com.    |
| .pl.     |
| .uk.     |
| .hn.     |
| .id.     |
| .ie.     |
+----------+

我想打印出 dnstomain 及其相关的顶级域名。我执行以下 mysql 查询:

select test.dnsdomain , tld.tld from test join tld where locate(tld.tld, test.dnsdomain, length(test.dnsdomain) - length (tld.tld) )!= 0; 

并得到以下 table:

+---------------------------+----------+
| dnsdomain                 | tld      |
+---------------------------+----------+
| ns2.hosting.indo.net.id.  | .net.id. |
| ns1.onepanel.indo.net.id. | .net.id. |
| ns-1591.awsdns-06.co.uk.  | .co.uk.  |
| mail189.atl21.rsgsv.net.  | .net.    |
| gli.websitewelcome.com.   | .com.    |
| ns2.metrolink.pl.         | .pl.     |
| ns1.metrolink.pl.         | .pl.     |
| ns-1591.awsdns-06.co.uk.  | .uk.     |
| NS3.METRORED.HN.          | .hn.     |
| NS.METRORED.HN.           | .hn.     |
| ns2.hosting.indo.net.id.  | .id.     |
| ns1.onepanel.indo.net.id. | .id.     |
| www.csis.ul.ie.           | .ie.     |
+---------------------------+----------+

我的查询的问题是,对于 table 'test' 中的每条记录,它不会检查 table 'tld' 中的所有顶级域名,这就是我看到一些东西的原因喜欢:

| ns-1591.awsdns-06.co.uk.  | .uk.     |

预期结果如下:

| ns-1591.awsdns-06.co.uk.  | .co.uk.  |

我做错了什么?

你没有做错任何事。 dnsname 'blah.co.uk.' 匹配 '.co.uk.''.uk.'。两行都在 returned.

听起来您想过滤掉除了 "longest" 匹配 tld.

之外的所有内容

注意:我更喜欢使用 RIGHT() 函数从 dnsdomain 中提取最右边的部分。 (这对我来说更容易理解,但它应该等同于您使用的表达式。)

参考:RIGHT() https://dev.mysql.com/doc/refman/5.5/en/string-functions.html#function_right

过滤掉较短匹配的一个选项是使用相关子查询来确定所有匹配的 tld 最大 长度,并且只有 return 具有该长度的 tld

例如:

SELECT test.dnsdomain
     , tld.tld
  FROM test
  JOIN tld 
    ON tld.tld = RIGHT(test.tndsdomain,CHAR_LENGTH(tld.tld))
 WHERE CHAR_LENGTH(tld.tld) = 
       ( SELECT MAX(CHAR_LENGTH(m.tld))
           FROM tld m
          WHERE m.tld = RIGHT(test.tndsdomain,CHAR_LENGTH(m.tld))
       )

您可以使用对内联视图的 JOIN 操作获得等效的结果,它的作用基本相同:

SELECT test.dnsdomain
     , tld.tld
  FROM test
  JOIN tld 
    ON tld.tld = RIGHT(test.tndsdomain,CHAR_LENGTH(tld.tld))
  JOIN ( SELECT n.dnsdomain
              , MAX(CHAR_LENGTH(m.tld)) AS tld_len 
           FROM test n
           JOIN tld m 
             ON m.tld = RIGHT(n.tndsdomain,CHAR_LENGTH(m.tld))
          GROUP BY n.dnsdomain
       ) o
    ON o.dnsdomain = test.dnsdomain
   AND o.tld_len = CHAR_LENGTH(tld.tld)

此外,使用 CHAR_LENGTH() 函数比 LENGTH() 函数更好。 LENGTH() 函数 returns 字节数,对于单字节字符集(如 latin1),与字符数相同,但对于多字节字符集,字符数可以小于字节数。)

试试 Group By 函数。此语句适用于 mysql :

select test.dnsdomain , tld.tld ,
max(length(tld.tld)) as x
from test 
join tld 
where locate(tld.tld, test.dnsdomain, length(test.dnsdomain) - length (tld.tld) )!= 0; 
group by test.tnsdomain

 select test.dnsdomain , max(tld.tld) as tld
    from test 
    join tld 
    where locate(tld.tld, test.dnsdomain, length(test.dnsdomain) - length (tld.tld) )!= 0; 
    group by test.tnsdomain