Oracle SQL:在多行列中查找特定字符的每个位置,而不重复

时间:2018-07-23 20:14:07

标签: sql string oracle duplicates

我正在尝试在字符串列中查找给定字符(¬)的位置。此方法对于单行效果很好,并且每次匹配时都正确返回一行与字符串位置的关系。但是,当我在其中添加更多行时,会导致重复。我添加的越多,生成的重复项就越多。

我已经计算出,如果N是输入行数,它将导致第一个匹配项显示1次,第二个匹配项显示N,第三个匹配项显示N ^ 2次,但无法弄清楚原因。

对于小型数据集,我可以使用一个独特的数据集,但是随着我添加更多的行和更多的匹配项,它很快变得运行起来太慢了。

我该如何解决此代码以使每个原始行的每个位置仅返回一行?

WITH TEST_TABLE AS (
SELECT 'test 1 ¬ test  ¬2' AS NOTE FROM DUAL 
UNION ALL SELECT 'test 3 ¬ tester ¬ 4 test yayay¬ay¬ay' AS NOTE FROM DUAL
UNION ALL SELECT 'test 5 ¬ tester ¬ 6' AS NOTE FROM DUAL
UNION ALL SELECT 'test 7 ¬ tester ¬ 8' AS NOTE FROM DUAL
)

SELECT  
    note, INSTR(NOTE,'¬', 1, LEVEL) POS, REGEXP_COUNT(NOTE, '¬')
    FROM test_table
    CONNECT BY LEVEL <= REGEXP_COUNT(NOTE, '¬')
    order by 1, 2
    ;

2 个答案:

答案 0 :(得分:2)

使用CROSS APPLY查询:

WITH TEST_TABLE AS (
SELECT 'test 1 ¬ test  ¬2' AS NOTE FROM DUAL 
UNION ALL SELECT 'test 3 ¬ tester ¬ 4 test yayay¬ay¬ay' AS NOTE FROM DUAL
UNION ALL SELECT 'test 5 ¬ tester ¬ 6' AS NOTE FROM DUAL
UNION ALL SELECT 'test 7 ¬ tester ¬ 8' AS NOTE FROM DUAL
)

SELECT  x.*
FROM TEST_TABLE t
CROSS APPLY (
    SELECT t.note, INSTR(t.NOTE,'¬', 1, LEVEL) POS, REGEXP_COUNT(t.NOTE, '¬')
    FROM dual
    CONNECT BY LEVEL <= REGEXP_COUNT(t.NOTE, '¬')
) x
    order by 1, 2
    ;

NOTE                                            POS REGEXP_COUNT(NOTE,'¬')
---------------------------------------- ---------- ----------------------
test 1 ¬ test  ¬2                                 8                      2
test 1 ¬ test  ¬2                                16                      2
test 3 ¬ tester ¬ 4 test yayay¬ay¬ay              8                      4
test 3 ¬ tester ¬ 4 test yayay¬ay¬ay             17                      4
test 3 ¬ tester ¬ 4 test yayay¬ay¬ay             31                      4
test 3 ¬ tester ¬ 4 test yayay¬ay¬ay             34                      4
test 5 ¬ tester ¬ 6                               8                      2
test 5 ¬ tester ¬ 6                              17                      2
test 7 ¬ tester ¬ 8                               8                      2
test 7 ¬ tester ¬ 8                              17                      2

10 rows selected.

答案 1 :(得分:1)

另一个选择:

SQL> WITH TEST_TABLE AS (
  2  SELECT 'test 1 ¬ test  ¬2' AS NOTE FROM DUAL
  3  UNION ALL SELECT 'test 3 ¬ tester ¬ 4 test yayay¬ay¬ay' AS NOTE FROM DUAL
  4  UNION ALL SELECT 'test 5 ¬ tester ¬ 6' AS NOTE FROM DUAL
  5  UNION ALL SELECT 'test 7 ¬ tester ¬ 8' AS NOTE FROM DUAL
  6  )
  7  SELECT
  8    note,
  9    INSTR(NOTE,'¬', 1, column_value) POS, REGEXP_COUNT(NOTE, '¬')
 10  FROM test_table,
 11       table(cast(multiset(select level from dual
 12                           CONNECT BY LEVEL <= REGEXP_COUNT(NOTE, '¬')
 13                          ) as sys.odcinumberlist))
 14  order by 1, 2;

NOTE                                            POS REGEXP_COUNT(NOTE,'¬')
---------------------------------------- ---------- ----------------------
test 1 ¬ test  ¬2                                 8                      2
test 1 ¬ test  ¬2                                16                      2
test 3 ¬ tester ¬ 4 test yayay¬ay¬ay              8                      4
test 3 ¬ tester ¬ 4 test yayay¬ay¬ay             17                      4
test 3 ¬ tester ¬ 4 test yayay¬ay¬ay             31                      4
test 3 ¬ tester ¬ 4 test yayay¬ay¬ay             34                      4
test 5 ¬ tester ¬ 6                               8                      2
test 5 ¬ tester ¬ 6                              17                      2
test 7 ¬ tester ¬ 8                               8                      2
test 7 ¬ tester ¬ 8                              17                      2

10 rows selected.

SQL>