0

我有 2 个表:errorlookup 和错误。errorlookup 有 2 列:代码和描述。代码长度为 2。错误有 2 列 id 和错误代码。错误代码的长度为 40,这意味着它们代码为每个 id 存储 20 个错误代码。我需要通过子串错误代码并与错误查找表中的代码匹配来显示与 id 关联的所有描述。错误查找的示例数据:

代码:描述
   12:无效
   22:不活动
   21:活跃

错误的样本数据:

id:错误代码
 1:1221
 2:2112
 3:1222

我不能使用 LIKE,因为它会导致太多错误。我希望将错误代码列分解为长度为 2 的字符串,然后加入错误查找。怎么做到呢?

4

3 回答 3

2

如果你真的不能改变表结构,这里有另一种方法:

创建辅助numbers表:

CREATE TABLE numbers
( i INT NOT NULL 
, PRIMARY KEY (i)
) ;

INSERT INTO numbers VALUES
( 1 ) ;   
INSERT INTO numbers VALUES
( 2 ) ;
--- ...
INSERT INTO numbers VALUES
( 100 ) ;

然后你可以使用这个:

SELECT err.id
     , err.errorcodes
     , num.i
     , look.codes
    , look.descriptionid
FROM
    ( SELECT i, 2*i-1 AS pos      --- odd numbers
      FROM numbers
      WHERE i <= 20               --- 20 pairs
    ) num 
  CROSS JOIN 
    errors  err
  JOIN 
    errorlookup  look
      ON look.codes = SUBSTR(err.errorcodes, pos, 2)
ORDER BY 
    err.errorcodes
  , num.i ;

测试:SQL-Fiddle

ID  ERRORCODES  I   CODES  DESCRIPTIONID
1   1221        1   12     Invalid
1   1221        2   21     Active
3   1222        1   12     Invalid
3   1222        2   22     Inactive
2   2112        1   21     Active
2   2112        2   12     Invalid
于 2012-05-05T00:10:16.917 回答
1

我认为最干净的解决方案是使用 PL/SQL 函数“规范化”您的错误代码表。这样,您可以保留当前(损坏的)表格设计,但仍可以访问其内容,就好像它已正确规范化一样。

create type error_code_type as object (id integer, code varchar(2))
/

create or replace type error_table as table of error_code_type
/

create or replace function unnest_errors
   return error_table pipelined
is  
  codes_l integer;
  i       integer;
  one_row error_code_type := error_code_type(null, null);
begin
  for err_rec in (select id, errorcodes from errors) loop
    codes_l := length(err_rec.errorcodes);
    i := 1;
    while i < codes_l loop
        one_row.id   := err_rec.id;
        one_row.code := substr(err_rec.errorcodes, i, 2);
        pipe row (one_row);
        i := i + 2;
    end loop;
  end loop;
end;
/

现在使用此功能,您可以执行以下操作:

select er.id, er.code, el.description
from table(unnest_errors) er
  join errorlookup el on el.codes = er.code;

您还可以基于该函数创建一个视图,以使语句更易于阅读:

create or replace view normalized_errorcodes 
as
select *
from table(unnest_errors);

然后您可以简单地引用真实语句中的视图。

(我在 11.2 上对此进行了测试,但我相信它也应该在 10.x 上工作)

于 2012-05-04T23:31:01.317 回答
0

我认为你在正确的轨道上LIKE。MySQL 有一个RLIKE允许通过正则表达式进行匹配的函数(我不知道它是否存在于 Oracle 中。)您可以将errorlookup.code其用作匹配errors.errorcodes. 该(..)*模式用于防止匹配“1213”之类的内容,例如“21”。

SELECT *
FROM error
JOIN errorlookup
WHERE errorcodes RLIKE CONCAT('^(..)*',code)
ORDER BY id;

+------+----------+------+
| id   | errorcode| code |
+------+----------+------+
|    1 | 11       | 11   |
|    2 | 1121     | 11   |
|    2 | 1121     | 21   |
|    3 | 21313245 | 21   |
|    3 | 21313245 | 31   |
|    3 | 21313245 | 32   |
|    4 | 21       | 21   |
+------+----------+------+
于 2012-05-04T19:03:25.627 回答