Stack Overflow em Português Asked by Enio Amarantes on November 7, 2021
Tenho uma sequência numérica em string tipo '0,1;2,2;5,3;8,4;'
.
Preciso que o resultado saia '1,2,3,4'
apenas os números após a virgula.
Já tentei a seguinte consulta:
{select replace(replace('0,1;2,2;5,3;8,4;', '[0-9'],', ''), ';', ',')}
Porém não substitui nada. Como faço para usar o operador que identifica qualquer numeral?
A solução que vou propor necessita que cada linha possua uma identificação única. Assim, para fins de demonstração da solução será considerada que essa identificação única existe.
-- código #1
CREATE TABLE tabela (ID_sequencia tinyint identity, Sequencia varchar(100));
INSERT into tabela values ('0,10;2,2;5,13;8,4');
go
Para separar os elementos será utilizada a função de usuário DelimitedSplit8K, de autoria de Jeff Moden. Informações sobre esta função estão disponíveis no artigo An Improved SQL 8K “CSV Splitter” Function, sendo que o código fonte dela também pode ser obtido no artigo Separar em partes uma lista de valores.
O primeiro passo é separar cada par:
-- código #2
SELECT ID_sequencia, T.sequencia, S1.ItemNumber as seqPar, S1.Item as Par
from tabela as T
cross apply dbo.DelimitedSplit8K (T.sequencia, ';') as S1;
Após separar cada par, deve-se obter cada elemento de cada par:
-- código #3
with
gPar as (
SELECT ID_sequencia, T.sequencia, S1.ItemNumber as seqPar, S1.Item as Par
from tabela as T
cross apply dbo.DelimitedSplit8K (T.sequencia, ';') as S1
),
gElemento as (
SELECT P.ID_Sequencia, P.sequencia, P.seqPar,
S2.ItemNumber as seqElemento, S2.Item as Elemento
from gPar as P
cross apply dbo.DelimitedSplit8K (P.Par, ',') as S2
)
SELECT ID_Sequencia, sequencia, seqPar, seqElemento, Elemento
from gElemento
order by ID_Sequencia, seqPar;
Tendo-se cada elemento separado, o passo final é agrupar os elementos finais de cada par, na ordem de cada par. Eis o código SQL completo, utilizando a função STRING_AGG para agrupar os elementos:
-- código #4
-- Autor: José Diz
with
gPar as (
SELECT ID_sequencia, T.sequencia, S1.ItemNumber as seqPar, S1.Item as Par
from tabela as T
cross apply dbo.DelimitedSplit8K (T.sequencia, ';') as S1
),
gElemento as (
SELECT P.ID_Sequencia, P.sequencia, P.seqPar,
S2.ItemNumber as seqElemento, S2.Item as Elemento
from gPar as P
cross apply dbo.DelimitedSplit8K (P.Par, ',') as S2
)
SELECT ID_Sequencia,
string_agg (Elemento, ',') within group (order by seqPar)
from gElemento
where seqElemento = 2
group by ID_Sequencia;
Como a função STRING_AGG somente funciona a partir da versão 2017 do SQL Server, ela pode ser substituída pela técnica blackbox xml nas versões anteriores do SQL Server. Detalhes no artigo Concatenação de várias linhas de uma mesma coluna.
-- código #5 v2
-- Autor: José Diz
with
gPar as (
SELECT ID_sequencia, T.sequencia, S1.ItemNumber as seqPar, S1.Item as Par
from tabela as T
cross apply dbo.DelimitedSplit8K (T.sequencia, ';') as S1
),
gElemento as (
SELECT P.ID_Sequencia, P.sequencia, P.seqPar,
S2.ItemNumber as seqElemento, S2.Item as Elemento
from gPar as P
cross apply dbo.DelimitedSplit8K (P.Par, ',') as S2
)
SELECT E.ID_Sequencia,
--string_agg (Elemento, ',') within group (order by seqPar)
stuff ((SELECT ',' + T.Elemento
from gElemento as T
where T.ID_Sequencia = E.ID_Sequencia
and T.seqElemento = 2
order by T.seqPar
for xml path(''), TYPE).value('.', 'varchar(max)'),
1, 1, '') as novaSequencia
from gElemento as E
where E.seqElemento = 2
group by E.ID_Sequencia;
Answered by José Diz on November 7, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP