问:我想在列表上创建内部联结,在该联结中的数值的保存方式很不相同,例如,在一个列中为application:username,在另一个列中为username(而不是以application开头)。举例说明一下怎样做吗?
答:这里我们是用string函数来完成从application:username值中提取username这一任务的。
看一下下面这些示例表:
Table1 Table2 username username Tom asdf:Tom Dick asdf:Dick Harry asdf:Harry qwerty:Tom qwerty:Dick qwerty:Harry asdfTom Tom oops: |
这里我们要用到SUBSTRING函数从string值中提取子字符串(substring)。但是如果应用值的长度不一样该怎么办呢?所以我们需要在username列中的不同的地方用到子字符串,这要根据冒号所处的地方不同而不同。
以上任务是由POSITION函数来完成的。
SELECT Table1.username , Table2.username FROM Table1 INNER JOIN Table2 ON SUBSTRING(Table2.username FROM POSITION(':' IN Table2.username) + 1 ) = Table1.username |
这里POSITION函数在Table2.username中找到了冒号的位置。asdf:username中位于第5位,qwerty:username中位于第7位。加上1后,我们可以在下一个字符中抽取子字符串。由于没有指定FOR长度,子字符串始终都是完全一致的。抽取出来的字字符串就好比是Table1.username相对应的行。
如果Table2.username值不包括冒号,那么POSITION函数返回的数为0。增加1,我们就可以抽取第一个字符串的子字符串。因此,整个值都为Table1.username匹配行。这个结果可能(或可能不)在匹配中获得结果,因为也要取决于数据,但是至少会执行查询。我们要加1,仅仅是因为 SUBSTRING函数的FROM 0值通常执行不会成功。
另外一个问题就是Table2.username值包括一个冒号。这样的话POSITION值就等于字符串的长度,FROM值也大于1。所以SUBSTRING函数同样还会执行失败。此时你只需要在 Table2.username值上加上一个空格。
ON SUBSTRING(Table2.username || ' ' FROM POSITION(':' IN Table2.username) + 1 ) = Table1.username |
如果冒号在最后,SUBSTRING函数就会返回空格。当然,它不会与Table1.username的任何值相匹配,所以十分安全。幸好与数值匹配时尾随空格(trailing spaces)不是很重要,所以另一些行可能会继续联结。