Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Split-Funktion in SQL Server 2008

Erstens besteht Ihre beste Lösung darin, Daten nicht in einer durch Kommas getrennten Liste in Ihrer Datenbank zu speichern. Sie sollten erwägen, die Tabellenstruktur zu korrigieren.

Wenn Sie die Tabellenstruktur nicht ändern können, müssen Sie die Daten in der Liste in Zeilen aufteilen, um den richtigen Namen zuzuweisen. Sobald die Daten aufgeteilt sind, können Sie die Daten wieder in der Liste verketten.

Es gibt viele verschiedene split Funktion, die Sie online finden können, aber hier ist eine Version, die ich normalerweise verwende:

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;

Um Ihr Ergebnis zu erhalten, würde ich damit beginnen, den split anzuwenden Funktion und eine row_number() da ich keinen eindeutigen Schlüssel sehe, der jeder Zeile zugeordnet ist. Wenn Sie für jede Zeile einen eindeutigen Schlüssel haben, benötigen Sie row_number() nicht :

;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

Diese Abfrage unterteilt Ihre durch Kommas getrennte Liste in Folgendes:

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

Sobald Sie die Daten in mehreren Zeilen mit dem richtigen name haben , dann können Sie STUFF() verwenden und FOR XML PATH um es in der Liste zu verketten. Ihre vollständige Abfrage würde etwa so aussehen:

;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;

Siehe SQL-Fiddle mit Demo.

Das Ergebnis der vollständigen Abfrage ist:

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