我有数百万个不同数字的数字3到8(121,1123,12345678等)。这不过是
1 st code + 2nd Code + 3rd Code = Number
"1" + "2" + "1" = 121
"123" + "45" + "678" = 1234567
"1234" + "" + "" = 1234
第2和第3代码可能为空白
我有另一个表,第一个代码作为主键和代码名称
在SQL(Oracle)中,我必须从每个数字中找出代码名称。我不关心第二代码和第三代码,如果找到最长匹配,考虑整数作为第一代码
在性能方面最好的方法是什么?
尝试一下这个,或许这个简单的解决方案对你来说足够快了吗?
-- assuming primary key in lookup table is a number
select subq.num,subq.matching_firstcode,
(select codename from codes ci where ci.firstcode = subq.matching_firstcode) codename
from (
select n.num,
greatest(
nvl(c8.firstcode,0),
nvl(c7.firstcode,0),
nvl(c6.firstcode,0),
nvl(c5.firstcode,0),
nvl(c4.firstcode,0),
nvl(c3.firstcode,0),
nvl(c2.firstcode,0),
nvl(c1.firstcode,0)
) matching_firstcode
from numbers n
left outer join codes c1 on c1.firstcode = to_number(substr(to_char(n.num), 1, 1))
left outer join codes c2 on c2.firstcode = to_number(substr(to_char(n.num), 1, 2))
left outer join codes c3 on c3.firstcode = to_number(substr(to_char(n.num), 1, 3))
left outer join codes c4 on c4.firstcode = to_number(substr(to_char(n.num), 1, 4))
left outer join codes c5 on c5.firstcode = to_number(substr(to_char(n.num), 1, 5))
left outer join codes c6 on c6.firstcode = to_number(substr(to_char(n.num), 1, 6))
left outer join codes c7 on c7.firstcode = to_number(substr(to_char(n.num), 1, 7))
left outer join codes c8 on c8.firstcode = to_number(substr(to_char(n.num), 1, 8))
) subq
;
如果你想要一个最长的比赛,我会尝试这样的事情:
select n.num,
max(c.firstcode) keep (dense_rank last order by length(c.firstcode)) as firstcode,
max(c.codename) keep (dense_rank last order by length(c.firstcode)) as codename
from numbers n
left join codes c on n.num like c.firstcode || '%'
group by n.num
order by 1, 2;
我在Peter的小提琴中使用了与@his answer基本相同的表格结构和数据。
为简洁起见,我也使用隐式强制转换来表示字符类型,尽管我建议使用显式强制转换(为了清晰起见),例如: length(to_char(c.firstcode))
而不是length(c.firstcode)
和to_char(n.num) like to_char(c.firstcode) || '%'
而不是n.num like c.firstcode || '%'
。
使用的样本数据: 表“数字”:
+---------+ | NUM | +---------+ | 121 | | 765 | | 1234 | | 3124 | | 1234567 | | 3124567 | +---------+
表“代码”:
+-----------+----------+ | FIRSTCODE | CODENAME | +-----------+----------+ | 1 | A | | 123 | B | | 312 | C | | 3124 | D | +-----------+----------+
查询结果:
+---------+-----------+----------+ | NUM | FIRSTCODE | CODENAME | +---------+-----------+----------+ | 121 | 1 | A | | 765 | | | | 1234 | 123 | B | | 3124 | 3124 | D | | 1234567 | 123 | B | | 3124567 | 3124 | D | +---------+-----------+----------+
这是一个SQL小提琴:http://www.sqlfiddle.com/#!4/958fed/1
编辑:此查询将受益于“num”和“firstcode”列是字符列(和索引)而不是数字列。