AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 237182
Accepted
youcantryreachingme
youcantryreachingme
Asked: 2019-05-02 22:42:09 +0800 CST2019-05-02 22:42:09 +0800 CST 2019-05-02 22:42:09 +0800 CST

Como substituir várias partes de uma string por dados de várias linhas?

  • 772
  • Aqui está um violino para mostrar o que estou procurando .

Dada uma tabela com duas colunas - um ID inteiro e uma string baseada em texto - quero começar com um valor de string que codifique qualquer número de inteiros entre chaves, misturados com quaisquer outros caracteres de texto válidos.

Exemplo:'{1} / {9} ... {12}'

Com uma única SELECTinstrução, quero retornar uma string pela qual todos os inteiros (e suas chaves) foram substituídos por um valor derivado da minha tabela; especificamente, o valor de texto para a linha com um ID que corresponde ao número encontrado na string de origem.... e quaisquer caracteres fora das chaves permanecem intocados.

Aqui está um exemplo que não consegue concluir a tarefa:

select
  replace('{13} {15}','{'+cast(id as varchar)+'}',isNull(display,''))
from testing;

Isso retornaria 1 linha por linha na testingtabela. Para a linha com idvalor = 13, a parte '{13}' da string é substituída com sucesso, mas a parte '{15}' não é (e vice-versa na linha 15).

Imagino que criar uma função que percorra todas as testinglinhas e tente repetidamente substituições resolveria o problema. Seja como for, uma instrução SQL direta seria preferível ao loop.

Dados de exemplo

+----+-------------------+
| id |  display          |
+----+-------------------+
|  1 |  Apple            |
|  2 |  Banana           |
|  3 |  Celery           |
|  4 |  Dragonfruit      |
|  5 |  Eggplant         |
|  6 |  Fenugreek        |
|  7 |  Gourd            |
|  8 |  Honeydew         |
|  9 |  Iceberg Lettuce  |
| 10 |  Jackfruit        |
| 11 |  Kale             |
| 12 |  Lemon            |
| 13 |  Mandarin         |
| 14 |  Nectarine        |
| 15 |  Olive            |
+----+-------------------+

Casos de uso de exemplo

select replace('{1} {3}',null,null) 
-- Returns 'Apple Celery'

select replace('{3},{4},{5}',null,null); 
-- Returns 'Celery,Dragonfruit,Eggplant'

select replace('{1} / {9} ... {12}',null,null); 
-- Returns 'Apple / Iceberg Lettuce ... Lemon'

Claramente, a palavra- replacechave não faz o trabalho.

PS. Se uma solução exigir que o formato da string seja alterado para facilitar isso, essa é uma opção.

Por exemplo: '#1 / #9 ... #12'(para correlacionar com o exemplo anterior)

Nesse formato, talvez pudéssemos dividir a string em um conjunto de linhas, com base em #, pegar os leftcaracteres até encontrarmos um não numérico, joinpara a testingtabela com base nos números obtidos, substituir os #e números pelo valor testingda tabela e displaydepois stufftodos individualmente tokens modificados de volta em uma única string for xml path?

Estou usando o SQL Server 2016, que não oferece suporte ao string_agg. Dito isso, se houver uma solução usando string_agg, ainda estou interessado em analisá-la.

sql-server t-sql
  • 2 2 respostas
  • 6176 Views

2 respostas

  • Voted
  1. Best Answer
    Scott Hodgin - Retired
    2019-05-03T01:34:32+08:002019-05-03T01:34:32+08:00

    Aqui está um exemplo de como usar um recursivo ctepara traduzir as variáveis

    drop table if exists testing;
    go
    create table testing (id int, display varchar(16));
    insert into testing values (1, 'Apple');
    insert into testing values (2, 'Banana');
    insert into testing values (3, 'Celery');
    insert into testing values (4, 'Dragonfruit');
    insert into testing values (5, 'Eggplant');
    
    DROP FUNCTION IF EXISTS dbo.TranslateVariables
    go
    CREATE FUNCTION dbo.TranslateVariables
    (
        @StringValue VARCHAR(MAX)
    )
    RETURNS TABLE
    
    AS
    RETURN (
    
    --Common Table Expression for Translation
    WITH TranslationTable
    AS (
        SELECT FindValue = '{' + convert(varchar(5),id) + '}' ,ReplaceValue = display,ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS rn
        FROM testing
        )
    --Recursive CTE to loop through the TranslationTable and replace FindValue with ReplaceValue
    ,RecursiveCte as
    (
    SELECT @StringValue AS StrValue
        ,(
            SELECT count(*)
            FROM TranslationTable
            ) AS cnt
    
    UNION ALL
    
    SELECT replace(StrValue, tt.FindValue, tt.Replacevalue)
        ,cnt - 1
    FROM RecursiveCte
    JOIN TranslationTable tt
        ON tt.rn = cnt )
    
    SELECT StrValue
        ,cnt
    FROM RecursiveCte where cnt = 0
        )
    go
    

    --Verify translation
    SELECT *
    FROM dbo.TranslateVariables('{1} {3}')
    OPTION (MAXRECURSION 32767) -- Don't forget to use the maxrecursion option!
    

     StrValue     | cnt |
    |--------------|-----|
    | Apple Celery | 0   |
    

    SELECT *
    FROM dbo.TranslateVariables('{3},{4},{5}')
    OPTION (MAXRECURSION 32767) -- Don't forget to use the maxrecursion option!
    

    | StrValue                    | cnt |
    |-----------------------------|-----|
    | Celery,Dragonfruit,Eggplant | 0   |
    
    • 4
  2. Peter Vandivier
    2019-05-03T01:31:47+08:002019-05-03T01:31:47+08:00

    Supondo que você esteja em uma versão que o suporte (e desative a versão em seu violino original ), você pode usar as funções nativas string_split()& string_agg().

    declare @id_list varchar(10) = '1,3'; -- for 'Apple,Celery' 
    -- set @id_list = '3,4,5'; --for 'Celery,Dragonfruit,Eggplant'
    
    select string_agg(display, ',') as agg
    from (
        select t.display 
        from testing t
        cross apply string_split(@id_list,',') ss 
        where try_cast(ss.[value] as int) = t.id
    ) x;
    

    O exemplo anterior pressupõe que você abandonou as chaves no caminho e é apenas uma lista de números separados por vírgula. Se você quiser manter as chaves no caminho, tente impor que ele esteja chegando como um JSON bem formado e use algumas das funções JSON nativas para analisá-lo. Os bits-chave acima são:

    1. fornecer uma matriz de [Id]s para ...
    2. filtrar apenas os testing.displays que você deseja e depois ...
    3. ...alimentar essa matriz de texto parastring_agg()

    Dado o esclarecimento de que você está em 2016, e que string_agg()só estará disponível em 2017, você ainda pode usar string_split()para criar a matriz conforme necessário e usar uma das abordagens herdadas que contornam a ausência de string_agg()como você menciona considerando no OP. Por exemplo:

    select stuff(agg,1,1,'') as agg_trim_first_comma
    from (
        select stuff(x.display,1,0,'') 
        from (
            select ',' + t.display 
            from testing t
            cross apply string_split('1,3',',') ss 
            where try_cast(ss.[value] as int) = t.id
        ) x (display )
        for xml path('')
    ) y (agg);
    
    • 0

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve