sql >> Databáze >  >> RDS >> Sqlserver

Funkce rozdělení v SQL Server 2008

Za prvé, nejlepším řešením je neukládat data do seznamu v databázi odděleného čárkami. Měli byste zvážit opravu struktury tabulky.

Pokud nemůžete změnit strukturu tabulky, budete muset rozdělit data v seznamu do řádků, abyste přiřadili správný název. Jakmile jsou data rozdělena, můžete je zřetězit zpět do seznamu.

Existuje mnoho různých split funkce, kterou můžete najít online, ale zde je verze, kterou obvykle používám:

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;

Chcete-li získat váš výsledek, začal bych použitím split funkce a row_number() protože nevidím jedinečný klíč spojený s každým řádkem. Pokud máte na každém řádku jedinečný klíč, nebudete potřebovat 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

Tento dotaz rozdělí váš seznam oddělený čárkami na následující:

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

Jakmile budete mít data ve více řádcích se správným name , pak můžete použít STUFF() a FOR XML PATH zřetězit jej do seznamu. Váš úplný dotaz by byl podobný tomuto:

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

Viz SQL Fiddle s ukázkou.

Výsledek úplného dotazu je:

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


  1. Jaký typ JOIN použít

  2. Průvodce návrhem databáze pro systém sociálních sítí v MySQL

  3. Top 9 tipů pro nastavení vašeho SQL Server Clusteru

  4. Jak najít nečíselné hodnoty ve sloupci v MySQL