sql >> Base de Datos >  >> RDS >> Sqlserver

Función de división en SQL Server 2008

Primero, su mejor solución es no almacenar datos en una lista separada por comas en su base de datos. Debería considerar arreglar la estructura de la mesa.

Si no puede modificar la estructura de la tabla, deberá dividir los datos de la lista en filas para asignar el nombre correcto. Una vez que los datos se dividen, puede volver a concatenar los datos en la lista.

Hay muchos split diferentes función que puede encontrar en línea pero aquí hay una versión que normalmente uso:

CREATE FUNCTION [dbo].[Split](@String varchar(MAX), @Delimiter char(1))       
returns @temptable TABLE (items varchar(MAX))       
as       
begin      
    declare @idx int       
    declare @slice varchar(8000)       

    select @idx = 1       
        if len(@String)<1 or @String is null  return       

    while @idx!= 0       
    begin       
        set @idx = charindex(@Delimiter,@String)       
        if @idx!=0       
            set @slice = left(@String,@idx - 1)       
        else       
            set @slice = @String       

        if(len(@slice)>0)  
            insert into @temptable(Items) values(@slice)       

        set @String = right(@String,len(@String) - @idx)       
        if len(@String) = 0 break       
    end   
return 
end;

Para obtener su resultado, comenzaría aplicando split función y un row_number() ya que no veo una clave única asociada con cada fila. Si tiene una clave única en cada fila, entonces no necesitará el row_number() :

;with cte as
(
  select rn, name, id
  from
  (
    select row_number() over(order by (select 1)) rn,
      databasename
    from table2
  ) t2
  cross apply dbo.split(t2.databasename, ',') i
  inner join table1 t1
    on i.items = t1.id
) 
select *
from cte

Esta consulta divide su lista separada por comas en lo siguiente:

| RN |   NAME | ID |
--------------------
|  1 |  MSSQL |  1 |
|  1 | Oracle |  3 |
|  2 |  MySQl |  2 |
|  3 |  MSSQL |  1 |
|  3 |  MySQl |  2 |

Una vez que tenga los datos en varias filas con el name correcto , entonces puedes usar STUFF() y FOR XML PATH para concatenarlo en la lista. Su consulta completa sería similar a esto:

;with cte as
(
  select rn, name, id
  from
  (
    select row_number() over(order by (select 1)) rn,
      databasename
    from table2
  ) t2
  cross apply dbo.split(t2.databasename, ',') i
  inner join table1 t1
    on i.items = t1.id
) 
select  
  STUFF(
         (SELECT ', ' + c2.name
          FROM cte c2
          where c1.rn = c2.rn
          order by c2.id
          FOR XML PATH (''))
          , 1, 1, '') Databasename
from cte c1
group by c1.rn
order by c1.rn;

Consulte SQL Fiddle con demostración.

El resultado de la consulta completa es:

|   DATABASENAME |
------------------
|  MSSQL, Oracle |
|          MySQl |
|   MSSQL, MySQl |