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 / 112408
Accepted
Tufan Chand
Tufan Chand
Asked: 2015-08-28 04:51:51 +0800 CST2015-08-28 04:51:51 +0800 CST 2015-08-28 04:51:51 +0800 CST

Junte-se com valores separados por vírgula no SQL Server

  • 772

Eu tenho uma mesa [CourseMaster]LIKE

CourseId    CourseName
-----------------------
  01          ABC
  02          DEF
  03          GHI
  04          JKL
  05          MNO
  06          PQR
  07          STU

E eu tenho outra tabela [StudentMaster]para detalhes do aluno LIKE

ROLLNO  NAME    ADDRESS          Course
------------------------------------------------
12345   RAM     RAM ADDRESS      01,02,06                      
25695   HARI    HARI ADDRESS     02,06                         
89685   JEFF    JEFF ADDRESS     03,05,06,07                   
47896   DAISY   DAISY ADDRESS    03         

Aqui eu quero buscar os detalhes do aluno com CourseName(Not CourseId).

Se os valores em Coursenão forem separados por vírgula, seria muito simples querybuscar os detalhes com join.

A partir do meu conhecimento, posso executar dois queriespara o mesmo resultado que quero, uma consulta para buscar os detalhes do aluno [StudentMaster]no front-end. E outro para apenas buscar o CourseNamede [CourseMaster]correspondendo CourseIdatravés de um loop.

Mas o fato de eu querer o resultado por apenas um queryao invés de escrever dois queriespara esta pequena tarefa.

Acho que é 100% possível. E meu resultado esperado será:

ROLLNO  NAME    ADDRESS         Course
-------------------------------------------
12345   RAM     RAM ADDRESS     ABC,DEF,PQR                   
25695   HARI    HARI ADDRESS    DEF,PQR                       
89685   JEFF    JEFF ADDRESS    GHI,MNO,PQR,STU               
47896   DAISY   DAISY ADDRESS   GHI                 

Obrigado e qualquer sugestão valiosa será muito apreciada.

sql-server join
  • 4 4 respostas
  • 57257 Views

4 respostas

  • Voted
  1. Best Answer
    Aaron Bertrand
    2015-08-28T05:54:00+08:002015-08-28T05:54:00+08:00

    Você realmente deveria ter uma tabela de junção para os cursos que um aluno está fazendo, em vez de agrupar valores separados por vírgulas em uma única tupla. Se você acha que esse é o último problema que terá por causa desse design abaixo do ideal, terá uma grande surpresa. Você realmente deveria fazer com que os proprietários deste projeto lessem sobre normalização - sim, é doloroso alterar seu esquema, mas também está constantemente lidando com as limitações de deixá-lo como está.

    De qualquer forma, com isso dito, você precisa de uma função de divisão. Como seus valores separados por vírgula são numéricos, você pode se safar com uma variação da minha função XML; há vários outros para escolher nesta postagem do blog .

    CREATE FUNCTION dbo.SplitStrings_XML
    (
       @List       VARCHAR(MAX),
       @Delimiter  CHAR(1) = ','
    )
    RETURNS TABLE
    WITH SCHEMABINDING
    AS
       RETURN 
       (  
          SELECT Item = y.i.value('(./text())[1]', 'varchar(8000)')
          FROM 
          ( 
            SELECT x = CONVERT(XML, '<i>' 
              + REPLACE(@List, @Delimiter, '</i><i>') 
              + '</i>').query('.')
          ) AS a CROSS APPLY x.nodes('i') AS y(i)
       );
    

    Agora, sua consulta é:

    ;WITH x AS 
    (
      SELECT s.ROLLNO, s.Name, s.Address, c.CourseId, c.CourseName
      FROM dbo.StudentMaster AS s
      CROSS APPLY dbo.SplitStrings_XML(s.Course, default) AS f
      INNER JOIN dbo.CourseMaster AS c
      ON f.item = c.CourseId
    )
    SELECT ROLLNO, Name, Address, STUFF((
      SELECT ',' + CourseName FROM x AS x2 
      WHERE x2.ROLLNO = x.ROLLNO
      ORDER BY CourseId FOR XML PATH, 
      TYPE).value(N'.[1]',N'varchar(max)'), 1, 1, '')
    FROM x
    GROUP BY ROLLNO, Name, Address;
    

    Novamente, esta é uma solução complicada e, devido à sua estrutura de banco de dados inferior, a próxima consulta que você precisa executar será igualmente complicada e complicada. Há uma razão pela qual esse tipo de design é contestado em quase todos os blogs, ensaios ou livros sobre o assunto...

    Em versões mais modernas (SQL Server 2017 e superior), você pode combinar STRING_AGG()e STRING_SPLIT()tornar isso um pouco mais simples:

    SELECT s.ROLLNO, s.NAME, s.ADDRESS, STRING_AGG(c.CourseName, ',')
      FROM dbo.StudentMaster AS s
      CROSS APPLY STRING_SPLIT(s.Course, ',') AS f
      INNER JOIN dbo.CourseMaster AS c
      ON f.value = c.CourseId
      GROUP BY s.ROLLNO, s.NAME, s.ADDRESS;
    
    • 9
  2. Mikael Eriksson
    2015-08-28T23:03:20+08:002015-08-28T23:03:20+08:00

    Mesma solução que a fornecida por Aaron Bertrand quando se trata de construir os valores separados por vírgula, mas um pouco diferente na conexão CourseMaster.CourseIdcom os valores em StudentMaster.Course.

    SQL Fiddle

    Configuração do esquema do MS SQL Server 2014 :

    create table dbo.CourseMaster
    (
      CourseId char(2),
      CourseName char(3)
    );
    
    create table dbo.StudentMaster
    (
      ROLLNO char(5),
      NAME varchar(10),
      ADDRESS varchar(20),
      Course varchar(100)
    );
    
    insert into dbo.CourseMaster values
    ('01', 'ABC'),
    ('02', 'DEF'),
    ('03', 'GHI'),
    ('04', 'JKL'),
    ('05', 'MNO'),
    ('06', 'PQR'),
    ('07', 'STU');
    
    insert into dbo.StudentMaster values
    ('12345', 'RAM',   'RAM ADDRESS',   '01,02,06'),                      
    ('25695', 'HARI',  'HARI ADDRESS',  '02,06'),                         
    ('89685', 'JEFF',  'JEFF ADDRESS',  '03,05,06,07'),                   
    ('47896', 'DAISY', 'DAISY ADDRESS', '03');
    

    Pergunta 1 :

    select SM.ROLLNO,
           SM.NAME, 
           SM.ADDRESS,
           (
           select ','+CM.CourseName
           from dbo.CourseMaster as CM
           where ','+SM.Course+',' like '%,'+CM.CourseId+',%'
           for xml path(''), type
           ).value('substring(text()[1], 2)', 'varchar(max)') as Course
    from dbo.StudentMaster as SM;
    

    Resultados :

    | ROLLNO |  NAME |       ADDRESS |          Course |
    |--------|-------|---------------|-----------------|
    |  12345 |   RAM |   RAM ADDRESS |     ABC,DEF,PQR |
    |  25695 |  HARI |  HARI ADDRESS |         DEF,PQR |
    |  89685 |  JEFF |  JEFF ADDRESS | GHI,MNO,PQR,STU |
    |  47896 | DAISY | DAISY ADDRESS |             GHI |
    
    • 5
  3. keb
    2017-02-25T12:39:13+08:002017-02-25T12:39:13+08:00

    Uma maneira simples de obter os valores da lista da StudentMastertabela (e você pode juntar os resultados) seria (com a ajuda de uma string dividida como mencionado nas respostas anteriores, e assumindo que a função retorna uma coluna chamada item para cada item da lista) :

    SELECT ROLLNO, NAME, ADDRESS, item
    FROM StudentMaster
    CROSS APPLY fSplitString(Course);
    
    • 0
  4. user158308
    2018-08-13T06:17:44+08:002018-08-13T06:17:44+08:00
    select D.DATE,D.DESCP,
       (
       select ','+S.NAME
       from tb_schems as S
       where ',' + D.SCHME + ',' like '%,' + cast(S.id as nvarchar(20)) + ',%'
       for xml path(''), type
       ).value('substring(text()[1], 2)', 'varchar(max)') as SCHEME
    from TB_DETAIL as D;
    
    • 0

relate perguntas

  • Qual é a diferença entre um INNER JOIN e um OUTER JOIN?

  • 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 é a saída de uma instrução JOIN?

  • 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