Olá wkinoue,
Bem vindo ao forum GLUFKE.
Para a solução do seu problema, vamos em partes:
Primeiro, teremos que remover da string tudo aquilo que não nos interessa, ou seja, todos os caracteres que não sejam "números" ou "pipe". Para isso, podemos usar a função "REGEXP_REPLACE" com o filtro "[^0-9\|]", onde só mantemos os digitos numericos e o pipe. Execute a querie abaixo:
Selecionar tudo
SQL> SELECT
'[LOG]2331|1321{VP}|4524|5512]|885|4242113234{eddx]|5424|4524' MINHA_STRING,
REGEXP_REPLACE('[LOG]2331|1321{VP}|4524|5512]|885|4242113234{eddx]|5424|4524', '[^0-9\|]','') MINHA_STRING_FILTRADA
FROM DUAL
SQL>
MINHA_STRING MINHA_STRING_FILTRADA
------------------------------------------------------------ ------------------------------------------
[LOG]2331|1321{VP}|4524|5512]|885|4242113234{eddx]|5424|4524 2331|1321|4524|5512|885|4242113234|5424|4524
Pronto ! Note que você tem uma linha somente com os valores numéricos, separados por pipe :
2331|1321|4524|5512|885|4242113234|5424|4524
Agora, vamos tentar identificar quantos valores existem na string. Você disse que o separador oficial seria o "pipe". Então, vamos repetir o comando REGEXP_REPLACE para identificar quantos pipes existem na string. Neste caso, vou usar o filtro "[^|]" para só manter o pipe da string inicial:
Selecionar tudo
SQL> SELECT REGEXP_REPLACE('2331|1321|4524|5512|885|4242113234|5424|4524', '[^|]','') TOTAL
FROM DUAL;
TOTAL
-------
|||||||
Mas fica muito chato ficar contando os "pauzinhos" resultandes da querie. Vamos melhorar a mesma com a ajuda dos comandos LENGTH e TRIM:
Selecionar tudo
SQL> SELECT LENGTH(TRIM(REGEXP_REPLACE('2331|1321|4524|5512|885|4242113234|5424|4524', '[^|]',''))) TOTAL
2 FROM DUAL;
TOTAL
----------
7
OK .. então até aqui já temos a "string purificada" e quantos valores numericos se encontram na string, com base na contagens dos separadores "pipe".
Para isso, precisamos do comando "REGEXP_SUBSTR ... CONNECT BY LEVEL ...". Execute agora esta querie
Selecionar tudo
SQL> SELECT trim(regexp_substr('2331|1321|4524|5512|885|4242113234|5424|4524', '[^|]+', 1, LEVEL)) RESULTADO
2 FROM dual
3 CONNECT BY LEVEL <= 7+1;
RESULTADO
--------------------------------------------------------------------------------
2331
1321
4524
5512
885
4242113234
5424
4524
Algumas explicações:
- Note no comando REGEXP_SUBTR que eu informei o segundo parâmetro como '[^|]+'. Isso indica para ele que este é o separador de valores.
- Note no LEVEL que eu adicionei 1 ao valor (ex: 7+1). O motivo é que os separadores sempre estão um número a menos do que o total dos registros.
- Note que eu usei LENGTH e REGEXP_REPLACE para identificar quantos separadores existem. No 10g este é a forma de se fazer isso. No 11g eu passo a usar a função REGEXP_COUNT
Bem .. agora vamos verificar qual a distribuicao destas valores na string. Vamos colocar a querie anterior dentro de um
SELECT .. COUNT(*) FROM .. GROUP BY
.
Execute agora:
Selecionar tudo
SQL> SELECT RESULTADO,COUNT(*)
2 FROM
3 (
4 SELECT trim(regexp_substr('2331|1321|4524|5512|885|4242113234|5424|4524', '[^|]+', 1, LEVEL)) RESULTADO
5 FROM dual
6 CONNECT BY LEVEL <= 7+1
7 )
8 GROUP BY RESULTADO;
RESULTADO COUNT(*)
---------- ----------
4524 2
1321 1
5424 1
5512 1
2331 1
885 1
4242113234 1
Finalizamos então a contagem que você precisava fazer. Eu vou agora então repetir esta querie agregando nela tudo o que explicamos anteriormente:
Selecionar tudo
SQL> SELECT RESULTADO,COUNT(*)
2 FROM
3 (
4 SELECT trim(regexp_substr(REGEXP_REPLACE('[LOG]2331|1321{VP}|4524|5512]|885|4242113234{eddx]|5424|4524', '[^0-9\|]',''), '[^|]+', 1, LEVEL)) RESULTADO
5 FROM dual
6 CONNECT BY LEVEL <= LENGTH(TRIM(REGEXP_REPLACE('[LOG]2331|1321{VP}|4524|5512]|885|4242113234{eddx]|5424|4524', '[^|]','')))+1
7 )
8 GROUP BY RESULTADO
9 /
RESULTADO COUNT(*)
---------- ----------
4524 2
1321 1
5424 1
5512 1
2331 1
885 1
4242113234 1
Eu desenvolvi esta explicação por meio de consultas a sites na internet, que estou postando aqui:
http://www.sqlsnippets.com/en/topic-12818.html
http://stackoverflow.com/questions/1099 ... gits-again
Espero ter resolvido o seu problema, e agradeço por ter postado este assunto, uma vez que não tinha me deparado ainda com este tipo de problema.
Abraços,
Sergio Coutinho