如何在SQL(Oracle)中使用给定的数字查找代码名称

问题描述 投票:0回答:2

我有数百万个不同数字的数字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)中,我必须从每个数字中找出代码名称。我不关心第二代码和第三代码,如果找到最长匹配,考虑整数作为第一代码

在性能方面最好的方法是什么?

sql oracle database-performance
2个回答
1
投票

尝试一下这个,或许这个简单的解决方案对你来说足够快了吗?

-- 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
;

http://www.sqlfiddle.com/#!4/443624/1/0


1
投票

如果你想要一个最长的比赛,我会尝试这样的事情:

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”列是字符列(和索引)而不是数字列。

© www.soinside.com 2019 - 2024. All rights reserved.