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 / 295372
Accepted
zerodoc
zerodoc
Asked: 2021-07-08 09:41:20 +0800 CST2021-07-08 09:41:20 +0800 CST 2021-07-08 09:41:20 +0800 CST

INSERIR ou ATUALIZAR os valores de uma tabela A nas colunas da tabela B com base no valor da tabela A em sua linha?

  • 772

Eu tenho uma tabela que contém nomes de atributos com valores, mas cada linha é um atributo com seu valor,

ItemId NomeAtributo do Item ItemAtributeValue
405 Inscrição Conexões de alta ampacidade
405 Cor Amarelo
405 Condições ambientais Estanque
405 Material Composto
406 Inscrição Conexões de alta ampacidade
406 Cor Azul
406 Material Latão

então eu criei outra tabela com todos os nomes de atributos possíveis para achatá-la para que cada linha contenha todos os valores para cada item.

ItemId Inscrição Cor Condições ambientais Material
405 Conexões de alta ampacidade Amarelo Estanque Composto
406 Conexões de alta ampacidade Azul Madeira

Como é possível pegar a primeira tabela e inserir os dados de cada itemId na tabela acima nas colunas correspondentes?

Também preciso considerar que existem mais de cem nomes de atributos diferentes e nem todos os itens terão cada atributo ou valor. Não tenho certeza de que direção devo seguir com esse problema.

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

2 respostas

  • Voted
  1. Best Answer
    Biju jose
    2021-07-08T10:35:13+08:002021-07-08T10:35:13+08:00
    select itemid, 
           MAX(case 
                  when itemattributename ='Application' then itemattributevalue 
                  ELSE NULL END),
           MAX(case 
                  when itemattributename ='Color' then itemattributevalue 
                  ELSE NULL END)Color,
           ISNULL(MAX(case 
                  when itemattributename ='Environmental Conditions' then 
                       itemattributevalue 
                  ELSE NULL END),'')[Environmental Conditions],
           MAX(case 
                  when itemattributename ='Material' then itemattributevalue 
                 ELSE  NULL  END)Material
      from item
     group by itemid
    

    A solução acima funciona apenas se você tiver um número definido de atributos, se houver um número N de atributos, você deve usar o pivô dinâmico para isso

    • 3
  2. Hannah Vernon
    2021-07-08T13:15:11+08:002021-07-08T13:15:11+08:00

    Para complementar a resposta já fornecida por Biju jose , aqui está uma maneira de fazer isso com SQL dinâmico. Se você adicionar novas linhas à dbo.eavtabela no meu exemplo, elas serão traduzidas automaticamente em novas colunas na saída.

    USE tempdb;
    GO
    
    DROP TABLE IF EXISTS dbo.eav;
    GO
    
    CREATE TABLE dbo.eav
    (
          [ItemId]              int             NOT NULL
        , [ItemAttributeName]   varchar(50)     NOT NULL
        , [ItemAttributeValue]  varchar(50)     NOT NULL
    );
    
    INSERT INTO dbo.eav ([ItemId], [ItemAttributeName], [ItemAttributeValue])
    VALUES
          (405, 'Application', 'High Ampacity Connections')
        , (405, 'Color', 'Yellow')
        , (405, 'Environmental Conditions', 'Watertight')
        , (405, 'Material', 'Composite')
        , (406, 'Application', 'High Ampacity Connections')
        , (406, 'Color', 'Blue')
        , (406, 'Material', 'Brass')
        , (407, 'Size', 'Small')
        , (407, 'Application', 'Stapler');
    
    DECLARE @dynamic_sql nvarchar(max) = N'SELECT src.ItemId, ';
    
    DROP TABLE IF EXISTS #names;
    
    SELECT e.ItemAttributeName
    INTO #names
    FROM dbo.eav e
    GROUP BY e.ItemAttributeName
    ORDER BY e.ItemAttributeName;
    
    SET @dynamic_sql = @dynamic_sql + (
        SELECT STRING_AGG(QUOTENAME(e.ItemAttributeName) + N' = MAX(' + QUOTENAME(e.ItemAttributeName) + N')', N', ')
        FROM #names e
        );
    
    SET @dynamic_sql = @dynamic_sql + N' FROM src GROUP BY src.[ItemId] ORDER BY src.[ItemId];'
    
    SET @dynamic_sql = (
        SELECT N'
    ;WITH src AS 
    (
        SELECT e.ItemId
            , ' + STRING_AGG(QUOTENAME(e.ItemAttributeName) + N' = CASE WHEN e.ItemAttributeName = ''' + e.ItemAttributeName + N''' THEN e.ItemAttributeValue ELSE NULL END', CHAR(13) + CHAR(10) + N'        , ')
        FROM #names e 
        ) 
        + '
        FROM dbo.eav e
    )
    ' 
        + @dynamic_sql + N'
    
    ';
    
    PRINT @dynamic_sql;
    EXEC sys.sp_executesql @dynamic_sql;
    

    A saída do acima se parece com:

    ItemId Inscrição Cor Condições ambientais Material Tamanho
    405 Conexões de alta ampacidade Amarelo Estanque Composto NULO
    406 Conexões de alta ampacidade Azul NULO Latão NULO
    407 Agrafador NULO NULO NULO Pequena

    Como você pode ver, minha saída inclui ItemId 407, com um atributo de Tamanho "Pequeno".

    Obviamente, à medida que o número exclusivo de ItemAttributeNamevalores aumenta, mais ampla a saída se torna. Parece improvável que você realmente queira fazer isso. O mais provável seria selecionar um ItemId específico e mostrar apenas as colunas aplicáveis.

    O exemplo abaixo se baseia no código acima para mostrar como você pode selecionar dinamicamente um específico ItemId(neste caso 407), para mostrar apenas as colunas relevantes:

    USE tempdb;
    GO
    
    DROP TABLE IF EXISTS dbo.eav;
    GO
    
    CREATE TABLE dbo.eav
    (
          [ItemId]              int             NOT NULL
        , [ItemAttributeName]   varchar(50)     NOT NULL
        , [ItemAttributeValue]  varchar(50)     NOT NULL
    );
    
    INSERT INTO dbo.eav ([ItemId], [ItemAttributeName], [ItemAttributeValue])
    VALUES
          (405, 'Application', 'High Ampacity Connections')
        , (405, 'Color', 'Yellow')
        , (405, 'Environmental Conditions', 'Watertight')
        , (405, 'Material', 'Composite')
        , (406, 'Application', 'High Ampacity Connections')
        , (406, 'Color', 'Blue')
        , (406, 'Material', 'Brass')
        , (407, 'Size', 'Small')
        , (407, 'Application', 'Stapler');
    
    
    DECLARE @ItemIdFilter int = 407;
    DECLARE @dynamic_sql nvarchar(max) = N'SELECT src.ItemId, ';
    
    DROP TABLE IF EXISTS #names;
    
    SELECT e.ItemAttributeName
    INTO #names
    FROM dbo.eav e
    WHERE e.ItemId = @ItemIdFilter
    GROUP BY e.ItemAttributeName
    ORDER BY e.ItemAttributeName;
    
    SET @dynamic_sql = @dynamic_sql + (
        SELECT STRING_AGG(QUOTENAME(e.ItemAttributeName) + N' = MAX(' + QUOTENAME(e.ItemAttributeName) + N')', N', ')
        FROM #names e
        );
    
    SET @dynamic_sql = @dynamic_sql + N' FROM src GROUP BY src.[ItemId] ORDER BY src.[ItemId];'
    
    SET @dynamic_sql = (
        SELECT N'
    ;WITH src AS 
    (
        SELECT e.ItemId
            , ' + STRING_AGG(QUOTENAME(e.ItemAttributeName) + N' = CASE WHEN e.ItemAttributeName = ''' + e.ItemAttributeName + N''' THEN e.ItemAttributeValue ELSE NULL END', CHAR(13) + CHAR(10) + N'        , ')
        FROM #names e 
        ) 
        + '
        FROM dbo.eav e
        WHERE e.ItemId = ' + CONVERT(nvarchar(20), @ItemIdFilter) + N'
    )
    ' 
        + @dynamic_sql + N'
    
    ';
    
    PRINT @dynamic_sql;
    EXEC sys.sp_executesql @dynamic_sql;
    

    A saída disso se parece com:

    ItemId Inscrição Tamanho
    407 Agrafador Pequena

    O T-SQL gerado dinamicamente para a saída acima se parece com:

    ;WITH src AS 
    (
        SELECT e.ItemId
            , [Application] = CASE WHEN e.ItemAttributeName = 'Application' THEN e.ItemAttributeValue ELSE NULL END
            , [Size] = CASE WHEN e.ItemAttributeName = 'Size' THEN e.ItemAttributeValue ELSE NULL END
        FROM dbo.eav e
        WHERE e.ItemId = 407
    )
    SELECT src.ItemId, [Application] = MAX([Application]), [Size] = MAX([Size]) FROM src GROUP BY src.[ItemId] ORDER BY src.[ItemId];
    
    • 2

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