【发布时间】:2017-04-30 14:20:02
【问题描述】:
根据我的另一个问题Using REGEXP_SUBSTR with Strings Qualifier,我正在尝试确定哪种方法更适合使用。
结果数据集应仅按正确顺序显示分隔符 PLE、# 和 ALL 之前的字符串。
包中已有的当前查询是这样的(DDL 和 DML 在帖子底部):
SELECT DATA1
, DECODE(SIGN(0 - instr(DATA1, 'PLE')), -1, SUBSTR(DATA1, 1, instr(DATA1, 'PLE') - 1)) GET_DATA_TILL_FIRST_PLE
, DECODE(SIGN(0 - instr(DATA1, '#')), -1, SUBSTR(DATA1, 1, instr(DATA1, '#') - 1)) GET_DATA_TILL_FIRST_NUM_SIGN
, DECODE(SIGN(0 - instr(DATA1, 'ALL')), -1, SUBSTR(DATA1, 1, instr(DATA1, 'ALL') - 1)) GET_DATA_TILL_FIRST_ALL
, NVL(DECODE(SIGN(0 - instr(DATA1, 'PLE')), -1, SUBSTR(DATA1, 1, instr(DATA1, 'PLE') - 1), 0,
DECODE(SIGN(0 - instr(DATA1, '#')), -1, SUBSTR(DATA1, 1, instr(DATA1, '#') - 1), 0,
DECODE(SIGN(0 - instr(DATA1, 'ALL')), -1, SUBSTR(DATA1, 1, instr(DATA1, 'ALL') - 1), DATA1), DATA1), DATA1), DATA1) PUT_THEM_ALL_TOGETHER
FROM table_x;
以下数据集的结果:
DATA1 | GET_DATA_TILL_FIRST_PLE | GET_DATA_TILL_FIRST_#_SIGN | GET_DATA_TILL_FIRST_ALL | PUT_THEM_ALL_TOGETHER
----------------------- | ----------------------- | --------------------------- | -------------------------- | ----------------------
STRING_EXAMPLE | STRING_EXAM | | | STRING_EXAM
TREE_OF_APPLES | TREE_OF_AP | | | TREE_OF_AP
FIRST_EXAMPLE | FIRST_EXAM | | | FIRST_EXAM
IMPLEMENTATION | IM | | | IM
PARIS | | | | PARIS
PLEONASM | | | | PLEONASM
XXXX 1 | | | | XXXX 1
XXXX YYYYYY 2 FFFFFFFFF | | | | XXXX YYYYYY 2 FFFFFFFFF
XXXX YYYYYY 5FFFFFFFFF | | | | XXXX YYYYYY 5FFFFFFFFF
OPOPOPOPO #09090 APPLE | OPOPOPOPO #09090 AP | OPOPOPOPO | OPOPOPOPO # | OPOPOPOPO #09090 AP
OPOPOPOPO BALL# | | OPOPOPOPO BALL | OPOPOPOPO B | OPOPOPOPO BALL
BALL IS #LIFE | | BALL IS | B | BALL IS
PS。我只需要PUT_THEM_ALL_TOGETHER 列,但我也包含了其他列并添加上下文。
我发现查询有点混乱且难以阅读,所以我尝试使用REGEXP_SUBSTR 并在@vkp 的建议下,我想出了以下查询
这会产生与上述相同的数据集。
SELECT DATA1
, REGEXP_SUBSTR(DATA1, '(.+?)PLE',1,1,null,1) GET_DATA_TILL_FIRST_PLE
, REGEXP_SUBSTR(DATA1, '(.+?)#',1,1,null,1) GET_DATA_TILL_FIRST_#_SIGN
, REGEXP_SUBSTR(DATA1, '(.+?)ALL',1,1,null,1) GET_DATA_TILL_FIRST_ALL
, COALESCE(REGEXP_SUBSTR(DATA1, '(.+?)PLE',1,1,null,1),
REGEXP_SUBSTR(DATA1, '(.+?)#',1,1,null,1),
REGEXP_SUBSTR(DATA1, '(.+?)ALL',1,1,null,1),
DATA1) PUT_THEM_ALL_TOGETHER
FROM table_x;
但是,从@MathGuy 的回答看来,INSTR 和 SUBSTR 的效率更高。
我在某种程度上对此进行了测试,这就是我得到的:
使用INSTR 和SUBSTR:
SET TIMING ON;
BEGIN
UPDATE table_x
SET DATA2 = NVL(DECODE(SIGN(0 - instr(DATA1, 'PLE')), -1, SUBSTR(DATA1, 1, instr(DATA1, 'PLE') - 1), 0,
DECODE(SIGN(0 - instr(DATA1, '#')), -1, SUBSTR(DATA1, 1, instr(DATA1, '#') - 1), 0,
DECODE(SIGN(0 - instr(DATA1, 'ALL')), -1, SUBSTR(DATA1, 1, instr(DATA1, 'ALL') - 1), DATA1), DATA1), DATA1), DATA1);
ROLLBACK;
END;
/
PL/SQL 过程成功完成。
经过:00:00:00.234
使用REGEXP_SUBSTR:
SET TIMING ON;
BEGIN
UPDATE table_x
SET DATA2 = COALESCE(REGEXP_SUBSTR(DATA1, '(.+?)PLE',1,1,null,1)
,REGEXP_SUBSTR(DATA1, '(.+?)#',1,1,null,1)
,REGEXP_SUBSTR(DATA1, '(.+?)ALL',1,1,null,1)
,DATA1);
ROLLBACK;
END;
/
PL/SQL 过程成功完成。
经过:00:00:00.236
虽然这是一个非常有限的测试数据,但它表明INSTR 和SUBSTR 的组合比REGEXP_SUBSTR 快一点。
为了可读性,使用REGEXP_SUBSTR 代替INSTR 和SUBSTR 是否可以忽略不计?
DML 和 DDL:
create table table_x
(
data1 varchar2(100)
,data2 varchar2(100)
);
INSERT INTO table_x (DATA1) VALUES ('STRING_EXAMPLE');
INSERT INTO table_x (DATA1) VALUES ('TREE_OF_APPLES');
INSERT INTO table_x (DATA1) VALUES ('FIRST_EXAMPLE');
INSERT INTO table_x (DATA1) VALUES ('IMPLEMENTATION');
INSERT INTO table_x (DATA1) VALUES ('PARIS');
INSERT INTO table_x (DATA1) VALUES ('PLEONASM');
INSERT INTO table_x (DATA1) VALUES ('XXXX 1');
INSERT INTO table_x (DATA1) VALUES ('XXXX YYYYYY 2 FFFFFFFFF');
INSERT INTO table_x (DATA1) VALUES ('XXXX YYYYYY 5FFFFFFFFF');
INSERT INTO table_x (DATA1) VALUES ('OPOPOPOPO #09090 APPLE');
INSERT INTO table_x (DATA1) VALUES ('OPOPOPOPO BALL#');
INSERT INTO table_x (DATA1) VALUES ('BALL IS #LIFE');
谢谢。
【问题讨论】:
-
Elapsed: 00:00:00.236- 这是 236 毫秒与 234 毫秒。您似乎在一个非常有限的数据集(少于几千条记录)上对其进行了测试。这样的测试是不可靠的——对于 DBMS 来说,几千条记录不算什么,这种差异也可能来自 DBMS 和您的客户端之间的网络延迟。请准备一个包含几百万行而不是几百或几千行的数据集,然后再次重复测试并进行测量。我敢打赌,正则表达式会输.. -
嗨@krokodilko,是的,这在上面的帖子中得到了承认。
-
@krokodilko - 这很有意义,但“现在做什么”也取决于 OP 的现实问题。如果在他的实际问题中,他的表中只有 5,000 行,那么他可能不在乎在具有 1000 万行的表上哪个解决方案“最好”。如果他有一个包含 5,000 行的表,他会更关心可读性和可维护性而不是性能。
-
@krokodilko - 话虽如此,谢谢你让我好奇地进行了一些测试。有关结果,请参阅我刚刚发布的单独答案。